authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-11 00:43:23-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-11 00:43:23-05:00
log10cea15cc3061272a0ed05fafe9e762f6454fafc
treefc8a9cae06d4232ebf22a71ef9c59986f57f38bb
parent2dd85d52cc4c4c6a32704f187b41a06401400f0c

IR: implement embedFile builtin


4 files changed, 81 insertions(+), 43 deletions(-)

src/all_types.hpp+7
...@@ -1406,6 +1406,7 @@ enum IrInstructionId {...@@ -1406,6 +1406,7 @@ enum IrInstructionId {
1406 IrInstructionIdMaxValue,1406 IrInstructionIdMaxValue,
1407 IrInstructionIdCompileErr,1407 IrInstructionIdCompileErr,
1408 IrInstructionIdErrName,1408 IrInstructionIdErrName,
1409 IrInstructionIdEmbedFile,
1409};1410};
14101411
1411struct IrInstruction {1412struct IrInstruction {
...@@ -1852,6 +1853,12 @@ struct IrInstructionCUndef {...@@ -1852,6 +1853,12 @@ struct IrInstructionCUndef {
1852 IrInstruction *name;1853 IrInstruction *name;
1853};1854};
18541855
1856struct IrInstructionEmbedFile {
1857 IrInstruction base;
1858
1859 IrInstruction *name;
1860};
1861
1855enum LValPurpose {1862enum LValPurpose {
1856 LValPurposeNone,1863 LValPurposeNone,
1857 LValPurposeAssign,1864 LValPurposeAssign,
src/codegen.cpp+1
...@@ -1878,6 +1878,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1878,6 +1878,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1878 case IrInstructionIdCInclude:1878 case IrInstructionIdCInclude:
1879 case IrInstructionIdCDefine:1879 case IrInstructionIdCDefine:
1880 case IrInstructionIdCUndef:1880 case IrInstructionIdCUndef:
1881 case IrInstructionIdEmbedFile:
1881 zig_unreachable();1882 zig_unreachable();
1882 case IrInstructionIdReturn:1883 case IrInstructionIdReturn:
1883 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);1884 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+64-43
...@@ -343,6 +343,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) {...@@ -343,6 +343,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) {
343 return IrInstructionIdErrName;343 return IrInstructionIdErrName;
344}344}
345345
346static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
347 return IrInstructionIdEmbedFile;
348}
349
346template<typename T>350template<typename T>
347static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {351static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
348 T *special_instruction = allocate<T>(1);352 T *special_instruction = allocate<T>(1);
...@@ -1344,6 +1348,15 @@ static IrInstruction *ir_build_c_undef(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1344,6 +1348,15 @@ static IrInstruction *ir_build_c_undef(IrBuilder *irb, Scope *scope, AstNode *so
1344 return &instruction->base;1348 return &instruction->base;
1345}1349}
13461350
1351static 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
1347static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,1360static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
1348 bool gen_error_defers, bool gen_maybe_defers)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,6 +2087,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
20742087
2075 return ir_build_err_name(irb, scope, node, arg0_value);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 case BuiltinFnIdMemcpy:2099 case BuiltinFnIdMemcpy:
2078 case BuiltinFnIdMemset:2100 case BuiltinFnIdMemset:
2079 case BuiltinFnIdAlignof:2101 case BuiltinFnIdAlignof:
...@@ -2085,7 +2107,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -2085,7 +2107,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
2085 case BuiltinFnIdBreakpoint:2107 case BuiltinFnIdBreakpoint:
2086 case BuiltinFnIdReturnAddress:2108 case BuiltinFnIdReturnAddress:
2087 case BuiltinFnIdFrameAddress:2109 case BuiltinFnIdFrameAddress:
2088 case BuiltinFnIdEmbedFile:
2089 case BuiltinFnIdCmpExchange:2110 case BuiltinFnIdCmpExchange:
2090 case BuiltinFnIdFence:2111 case BuiltinFnIdFence:
2091 case BuiltinFnIdDivExact:2112 case BuiltinFnIdDivExact:
...@@ -7141,6 +7162,45 @@ static TypeTableEntry *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstruct...@@ -7141,6 +7162,45 @@ static TypeTableEntry *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstruct
7141 return ira->codegen->builtin_types.entry_void;7162 return ira->codegen->builtin_types.entry_void;
7142}7163}
71437164
7165static 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}
71447204
71457205
7146static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {7206static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
...@@ -7243,6 +7303,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -7243,6 +7303,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
7243 return ir_analyze_instruction_c_define(ira, (IrInstructionCDefine *)instruction);7303 return ir_analyze_instruction_c_define(ira, (IrInstructionCDefine *)instruction);
7244 case IrInstructionIdCUndef:7304 case IrInstructionIdCUndef:
7245 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);7305 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
7306 case IrInstructionIdEmbedFile:
7307 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
7246 case IrInstructionIdCast:7308 case IrInstructionIdCast:
7247 case IrInstructionIdStructFieldPtr:7309 case IrInstructionIdStructFieldPtr:
7248 case IrInstructionIdEnumFieldPtr:7310 case IrInstructionIdEnumFieldPtr:
...@@ -7377,6 +7439,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7377,6 +7439,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7377 case IrInstructionIdMinValue:7439 case IrInstructionIdMinValue:
7378 case IrInstructionIdMaxValue:7440 case IrInstructionIdMaxValue:
7379 case IrInstructionIdErrName:7441 case IrInstructionIdErrName:
7442 case IrInstructionIdEmbedFile:
7380 return false;7443 return false;
7381 case IrInstructionIdAsm:7444 case IrInstructionIdAsm:
7382 {7445 {
...@@ -7390,45 +7453,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7390,45 +7453,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7390// TODO port over all this commented out code into new IR way of doing things7453// TODO port over all this commented out code into new IR way of doing things
73917454
73927455
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//static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,7456//static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
7433// BlockContext *context, AstNode *node)7457// BlockContext *context, AstNode *node)
7434//{7458//{
...@@ -7765,8 +7789,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7765,8 +7789,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7765// case BuiltinFnIdFrameAddress:7789// case BuiltinFnIdFrameAddress:
7766// mark_impure_fn(g, context, node);7790// mark_impure_fn(g, context, node);
7767// return builtin_fn->return_type;7791// return builtin_fn->return_type;
7768// case BuiltinFnIdEmbedFile:
7769// return analyze_embed_file(g, import, context, node);
7770// case BuiltinFnIdCmpExchange:7792// case BuiltinFnIdCmpExchange:
7771// return analyze_cmpxchg(g, import, context, node);7793// return analyze_cmpxchg(g, import, context, node);
7772// case BuiltinFnIdFence:7794// case BuiltinFnIdFence:
...@@ -8353,7 +8375,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -8353,7 +8375,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
8353// case BuiltinFnIdMinValue:8375// case BuiltinFnIdMinValue:
8354// case BuiltinFnIdMaxValue:8376// case BuiltinFnIdMaxValue:
8355// case BuiltinFnIdMemberCount:8377// case BuiltinFnIdMemberCount:
8356// case BuiltinFnIdEmbedFile:
8357// // caught by constant expression eval codegen8378// // caught by constant expression eval codegen
8358// zig_unreachable();8379// zig_unreachable();
8359// case BuiltinFnIdCompileVar:8380// case BuiltinFnIdCompileVar:
src/ir_print.cpp+9
...@@ -713,6 +713,12 @@ static void ir_print_c_undef(IrPrint *irp, IrInstructionCUndef *instruction) {...@@ -713,6 +713,12 @@ static void ir_print_c_undef(IrPrint *irp, IrInstructionCUndef *instruction) {
713 fprintf(irp->f, ")");713 fprintf(irp->f, ")");
714}714}
715715
716static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instruction) {
717 fprintf(irp->f, "@embedFile(");
718 ir_print_other_instruction(irp, instruction->name);
719 fprintf(irp->f, ")");
720}
721
716static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {722static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
717 ir_print_prefix(irp, instruction);723 ir_print_prefix(irp, instruction);
718 switch (instruction->id) {724 switch (instruction->id) {
...@@ -874,6 +880,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -874,6 +880,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
874 case IrInstructionIdCUndef:880 case IrInstructionIdCUndef:
875 ir_print_c_undef(irp, (IrInstructionCUndef *)instruction);881 ir_print_c_undef(irp, (IrInstructionCUndef *)instruction);
876 break;882 break;
883 case IrInstructionIdEmbedFile:
884 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
885 break;
877 }886 }
878 fprintf(irp->f, "\n");887 fprintf(irp->f, "\n");
879}888}