| ... | ... | @@ -343,6 +343,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) { |
| 343 | 343 | return IrInstructionIdErrName; |
| 344 | 344 | } |
| 345 | 345 | |
| 346 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) { |
| 347 | return IrInstructionIdEmbedFile; |
| 348 | } |
| 349 | |
| 346 | 350 | template<typename T> |
| 347 | 351 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 348 | 352 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -1344,6 +1348,15 @@ static IrInstruction *ir_build_c_undef(IrBuilder *irb, Scope *scope, AstNode *so |
| 1344 | 1348 | return &instruction->base; |
| 1345 | 1349 | } |
| 1346 | 1350 | |
| 1351 | static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { |
| 1352 | IrInstructionEmbedFile *instruction = ir_build_instruction<IrInstructionEmbedFile>(irb, scope, source_node); |
| 1353 | instruction->name = name; |
| 1354 | |
| 1355 | ir_ref_instruction(name); |
| 1356 | |
| 1357 | return &instruction->base; |
| 1358 | } |
| 1359 | |
| 1347 | 1360 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1348 | 1361 | bool gen_error_defers, bool gen_maybe_defers) |
| 1349 | 1362 | { |
| ... | ... | @@ -2074,6 +2087,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 2074 | 2087 | |
| 2075 | 2088 | return ir_build_err_name(irb, scope, node, arg0_value); |
| 2076 | 2089 | } |
| 2090 | case BuiltinFnIdEmbedFile: |
| 2091 | { |
| 2092 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 2093 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 2094 | if (arg0_value == irb->codegen->invalid_instruction) |
| 2095 | return arg0_value; |
| 2096 | |
| 2097 | return ir_build_embed_file(irb, scope, node, arg0_value); |
| 2098 | } |
| 2077 | 2099 | case BuiltinFnIdMemcpy: |
| 2078 | 2100 | case BuiltinFnIdMemset: |
| 2079 | 2101 | case BuiltinFnIdAlignof: |
| ... | ... | @@ -2085,7 +2107,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 2085 | 2107 | case BuiltinFnIdBreakpoint: |
| 2086 | 2108 | case BuiltinFnIdReturnAddress: |
| 2087 | 2109 | case BuiltinFnIdFrameAddress: |
| 2088 | | case BuiltinFnIdEmbedFile: |
| 2089 | 2110 | case BuiltinFnIdCmpExchange: |
| 2090 | 2111 | case BuiltinFnIdFence: |
| 2091 | 2112 | case BuiltinFnIdDivExact: |
| ... | ... | @@ -7141,6 +7162,45 @@ static TypeTableEntry *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstruct |
| 7141 | 7162 | return ira->codegen->builtin_types.entry_void; |
| 7142 | 7163 | } |
| 7143 | 7164 | |
| 7165 | static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionEmbedFile *instruction) { |
| 7166 | IrInstruction *name = instruction->name->other; |
| 7167 | if (name->type_entry->id == TypeTableEntryIdInvalid) |
| 7168 | return ira->codegen->builtin_types.entry_invalid; |
| 7169 | |
| 7170 | Buf *rel_file_path = ir_resolve_str(ira, name); |
| 7171 | if (!rel_file_path) |
| 7172 | return ira->codegen->builtin_types.entry_invalid; |
| 7173 | |
| 7174 | ImportTableEntry *import = get_scope_import(instruction->base.scope); |
| 7175 | // figure out absolute path to resource |
| 7176 | Buf source_dir_path = BUF_INIT; |
| 7177 | os_path_dirname(import->path, &source_dir_path); |
| 7178 | |
| 7179 | Buf file_path = BUF_INIT; |
| 7180 | os_path_resolve(&source_dir_path, rel_file_path, &file_path); |
| 7181 | |
| 7182 | // load from file system into const expr |
| 7183 | Buf file_contents = BUF_INIT; |
| 7184 | int err; |
| 7185 | if ((err = os_fetch_file_path(&file_path, &file_contents))) { |
| 7186 | if (err == ErrorFileNotFound) { |
| 7187 | ir_add_error(ira, &instruction->base, buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); |
| 7188 | return ira->codegen->builtin_types.entry_invalid; |
| 7189 | } else { |
| 7190 | ir_add_error(ira, &instruction->base, buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err))); |
| 7191 | return ira->codegen->builtin_types.entry_invalid; |
| 7192 | } |
| 7193 | } |
| 7194 | |
| 7195 | // TODO add dependency on the file we embedded so that we know if it changes |
| 7196 | // we'll have to invalidate the cache |
| 7197 | |
| 7198 | bool depends_on_compile_var = true; |
| 7199 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| 7200 | init_const_str_lit(out_val,&file_contents); |
| 7201 | |
| 7202 | return get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(&file_contents)); |
| 7203 | } |
| 7144 | 7204 | |
| 7145 | 7205 | |
| 7146 | 7206 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| ... | ... | @@ -7243,6 +7303,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 7243 | 7303 | return ir_analyze_instruction_c_define(ira, (IrInstructionCDefine *)instruction); |
| 7244 | 7304 | case IrInstructionIdCUndef: |
| 7245 | 7305 | return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction); |
| 7306 | case IrInstructionIdEmbedFile: |
| 7307 | return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction); |
| 7246 | 7308 | case IrInstructionIdCast: |
| 7247 | 7309 | case IrInstructionIdStructFieldPtr: |
| 7248 | 7310 | case IrInstructionIdEnumFieldPtr: |
| ... | ... | @@ -7377,6 +7439,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7377 | 7439 | case IrInstructionIdMinValue: |
| 7378 | 7440 | case IrInstructionIdMaxValue: |
| 7379 | 7441 | case IrInstructionIdErrName: |
| 7442 | case IrInstructionIdEmbedFile: |
| 7380 | 7443 | return false; |
| 7381 | 7444 | case IrInstructionIdAsm: |
| 7382 | 7445 | { |
| ... | ... | @@ -7390,45 +7453,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7390 | 7453 | // TODO port over all this commented out code into new IR way of doing things |
| 7391 | 7454 | |
| 7392 | 7455 | |
| 7393 | | //static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import, |
| 7394 | | // BlockContext *context, AstNode *node) |
| 7395 | | //{ |
| 7396 | | // assert(node->type == NodeTypeFnCallExpr); |
| 7397 | | // |
| 7398 | | // AstNode **first_param_node = &node->data.fn_call_expr.params.at(0); |
| 7399 | | // Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node); |
| 7400 | | // if (!rel_file_path) { |
| 7401 | | // return g->builtin_types.entry_invalid; |
| 7402 | | // } |
| 7403 | | // |
| 7404 | | // // figure out absolute path to resource |
| 7405 | | // Buf source_dir_path = BUF_INIT; |
| 7406 | | // os_path_dirname(import->path, &source_dir_path); |
| 7407 | | // |
| 7408 | | // Buf file_path = BUF_INIT; |
| 7409 | | // os_path_resolve(&source_dir_path, rel_file_path, &file_path); |
| 7410 | | // |
| 7411 | | // // load from file system into const expr |
| 7412 | | // Buf file_contents = BUF_INIT; |
| 7413 | | // int err; |
| 7414 | | // if ((err = os_fetch_file_path(&file_path, &file_contents))) { |
| 7415 | | // if (err == ErrorFileNotFound) { |
| 7416 | | // add_node_error(g, node, |
| 7417 | | // buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); |
| 7418 | | // return g->builtin_types.entry_invalid; |
| 7419 | | // } else { |
| 7420 | | // add_node_error(g, node, |
| 7421 | | // buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err))); |
| 7422 | | // return g->builtin_types.entry_invalid; |
| 7423 | | // } |
| 7424 | | // } |
| 7425 | | // |
| 7426 | | // // TODO add dependency on the file we embedded so that we know if it changes |
| 7427 | | // // we'll have to invalidate the cache |
| 7428 | | // |
| 7429 | | // return resolve_expr_const_val_as_string_lit(g, node, &file_contents); |
| 7430 | | //} |
| 7431 | | // |
| 7432 | 7456 | //static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, |
| 7433 | 7457 | // BlockContext *context, AstNode *node) |
| 7434 | 7458 | //{ |
| ... | ... | @@ -7765,8 +7789,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7765 | 7789 | // case BuiltinFnIdFrameAddress: |
| 7766 | 7790 | // mark_impure_fn(g, context, node); |
| 7767 | 7791 | // return builtin_fn->return_type; |
| 7768 | | // case BuiltinFnIdEmbedFile: |
| 7769 | | // return analyze_embed_file(g, import, context, node); |
| 7770 | 7792 | // case BuiltinFnIdCmpExchange: |
| 7771 | 7793 | // return analyze_cmpxchg(g, import, context, node); |
| 7772 | 7794 | // case BuiltinFnIdFence: |
| ... | ... | @@ -8353,7 +8375,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8353 | 8375 | // case BuiltinFnIdMinValue: |
| 8354 | 8376 | // case BuiltinFnIdMaxValue: |
| 8355 | 8377 | // case BuiltinFnIdMemberCount: |
| 8356 | | // case BuiltinFnIdEmbedFile: |
| 8357 | 8378 | // // caught by constant expression eval codegen |
| 8358 | 8379 | // zig_unreachable(); |
| 8359 | 8380 | // case BuiltinFnIdCompileVar: |