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 {
14061406 IrInstructionIdMaxValue,
14071407 IrInstructionIdCompileErr,
14081408 IrInstructionIdErrName,
1409 IrInstructionIdEmbedFile,
14091410};
14101411
14111412struct IrInstruction {
......@@ -1852,6 +1853,12 @@ struct IrInstructionCUndef {
18521853 IrInstruction *name;
18531854};
18541855
1856struct IrInstructionEmbedFile {
1857 IrInstruction base;
1858
1859 IrInstruction *name;
1860};
1861
18551862enum LValPurpose {
18561863 LValPurposeNone,
18571864 LValPurposeAssign,
src/codegen.cpp+1
......@@ -1878,6 +1878,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
18781878 case IrInstructionIdCInclude:
18791879 case IrInstructionIdCDefine:
18801880 case IrInstructionIdCUndef:
1881 case IrInstructionIdEmbedFile:
18811882 zig_unreachable();
18821883 case IrInstructionIdReturn:
18831884 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+64-43
......@@ -343,6 +343,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) {
343343 return IrInstructionIdErrName;
344344}
345345
346static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
347 return IrInstructionIdEmbedFile;
348}
349
346350template<typename T>
347351static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
348352 T *special_instruction = allocate<T>(1);
......@@ -1344,6 +1348,15 @@ static IrInstruction *ir_build_c_undef(IrBuilder *irb, Scope *scope, AstNode *so
13441348 return &instruction->base;
13451349}
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
13471360static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
13481361 bool gen_error_defers, bool gen_maybe_defers)
13491362{
......@@ -2074,6 +2087,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
20742087
20752088 return ir_build_err_name(irb, scope, node, arg0_value);
20762089 }
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 }
20772099 case BuiltinFnIdMemcpy:
20782100 case BuiltinFnIdMemset:
20792101 case BuiltinFnIdAlignof:
......@@ -2085,7 +2107,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
20852107 case BuiltinFnIdBreakpoint:
20862108 case BuiltinFnIdReturnAddress:
20872109 case BuiltinFnIdFrameAddress:
2088 case BuiltinFnIdEmbedFile:
20892110 case BuiltinFnIdCmpExchange:
20902111 case BuiltinFnIdFence:
20912112 case BuiltinFnIdDivExact:
......@@ -7141,6 +7162,45 @@ static TypeTableEntry *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstruct
71417162 return ira->codegen->builtin_types.entry_void;
71427163}
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
71467206static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
......@@ -7243,6 +7303,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
72437303 return ir_analyze_instruction_c_define(ira, (IrInstructionCDefine *)instruction);
72447304 case IrInstructionIdCUndef:
72457305 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
7306 case IrInstructionIdEmbedFile:
7307 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
72467308 case IrInstructionIdCast:
72477309 case IrInstructionIdStructFieldPtr:
72487310 case IrInstructionIdEnumFieldPtr:
......@@ -7377,6 +7439,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
73777439 case IrInstructionIdMinValue:
73787440 case IrInstructionIdMaxValue:
73797441 case IrInstructionIdErrName:
7442 case IrInstructionIdEmbedFile:
73807443 return false;
73817444 case IrInstructionIdAsm:
73827445 {
......@@ -7390,45 +7453,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
73907453// 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//
74327456//static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
74337457// BlockContext *context, AstNode *node)
74347458//{
......@@ -7765,8 +7789,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
77657789// case BuiltinFnIdFrameAddress:
77667790// mark_impure_fn(g, context, node);
77677791// return builtin_fn->return_type;
7768// case BuiltinFnIdEmbedFile:
7769// return analyze_embed_file(g, import, context, node);
77707792// case BuiltinFnIdCmpExchange:
77717793// return analyze_cmpxchg(g, import, context, node);
77727794// case BuiltinFnIdFence:
......@@ -8353,7 +8375,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
83538375// case BuiltinFnIdMinValue:
83548376// case BuiltinFnIdMaxValue:
83558377// case BuiltinFnIdMemberCount:
8356// case BuiltinFnIdEmbedFile:
83578378// // caught by constant expression eval codegen
83588379// zig_unreachable();
83598380// case BuiltinFnIdCompileVar:
src/ir_print.cpp+9
......@@ -713,6 +713,12 @@ static void ir_print_c_undef(IrPrint *irp, IrInstructionCUndef *instruction) {
713713 fprintf(irp->f, ")");
714714}
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
716722static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
717723 ir_print_prefix(irp, instruction);
718724 switch (instruction->id) {
......@@ -874,6 +880,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
874880 case IrInstructionIdCUndef:
875881 ir_print_c_undef(irp, (IrInstructionCUndef *)instruction);
876882 break;
883 case IrInstructionIdEmbedFile:
884 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
885 break;
877886 }
878887 fprintf(irp->f, "\n");
879888}