aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-12-11 00:43:23 -0500
committerAndrew Kelley <superjoe30@gmail.com>2016-12-11 00:43:23 -0500
commit10cea15cc3061272a0ed05fafe9e762f6454fafc (patch)
treefc8a9cae06d4232ebf22a71ef9c59986f57f38bb /src/ir.cpp
parent2dd85d52cc4c4c6a32704f187b41a06401400f0c (diff)
downloadzig-10cea15cc3061272a0ed05fafe9e762f6454fafc.tar.gz
zig-10cea15cc3061272a0ed05fafe9e762f6454fafc.zip
IR: implement embedFile builtin
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp107
1 files changed, 64 insertions, 43 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 09342123ac..f8259c536c 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -343,6 +343,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) {
return IrInstructionIdErrName;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
+ return IrInstructionIdEmbedFile;
+}
+
template<typename T>
static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -1344,6 +1348,15 @@ static IrInstruction *ir_build_c_undef(IrBuilder *irb, Scope *scope, AstNode *so
return &instruction->base;
}
+static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) {
+ IrInstructionEmbedFile *instruction = ir_build_instruction<IrInstructionEmbedFile>(irb, scope, source_node);
+ instruction->name = name;
+
+ ir_ref_instruction(name);
+
+ return &instruction->base;
+}
+
static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
bool gen_error_defers, bool gen_maybe_defers)
{
@@ -2074,6 +2087,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_err_name(irb, scope, node, arg0_value);
}
+ case BuiltinFnIdEmbedFile:
+ {
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
+ if (arg0_value == irb->codegen->invalid_instruction)
+ return arg0_value;
+
+ return ir_build_embed_file(irb, scope, node, arg0_value);
+ }
case BuiltinFnIdMemcpy:
case BuiltinFnIdMemset:
case BuiltinFnIdAlignof:
@@ -2085,7 +2107,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
case BuiltinFnIdBreakpoint:
case BuiltinFnIdReturnAddress:
case BuiltinFnIdFrameAddress:
- case BuiltinFnIdEmbedFile:
case BuiltinFnIdCmpExchange:
case BuiltinFnIdFence:
case BuiltinFnIdDivExact:
@@ -7141,6 +7162,45 @@ static TypeTableEntry *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstruct
return ira->codegen->builtin_types.entry_void;
}
+static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionEmbedFile *instruction) {
+ IrInstruction *name = instruction->name->other;
+ if (name->type_entry->id == TypeTableEntryIdInvalid)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ Buf *rel_file_path = ir_resolve_str(ira, name);
+ if (!rel_file_path)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ ImportTableEntry *import = get_scope_import(instruction->base.scope);
+ // figure out absolute path to resource
+ Buf source_dir_path = BUF_INIT;
+ os_path_dirname(import->path, &source_dir_path);
+
+ Buf file_path = BUF_INIT;
+ os_path_resolve(&source_dir_path, rel_file_path, &file_path);
+
+ // load from file system into const expr
+ Buf file_contents = BUF_INIT;
+ int err;
+ if ((err = os_fetch_file_path(&file_path, &file_contents))) {
+ if (err == ErrorFileNotFound) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
+ return ira->codegen->builtin_types.entry_invalid;
+ } else {
+ ir_add_error(ira, &instruction->base, buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ }
+
+ // TODO add dependency on the file we embedded so that we know if it changes
+ // we'll have to invalidate the cache
+
+ bool depends_on_compile_var = true;
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
+ init_const_str_lit(out_val,&file_contents);
+
+ return get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(&file_contents));
+}
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
@@ -7243,6 +7303,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_c_define(ira, (IrInstructionCDefine *)instruction);
case IrInstructionIdCUndef:
return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
+ case IrInstructionIdEmbedFile:
+ return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
case IrInstructionIdCast:
case IrInstructionIdStructFieldPtr:
case IrInstructionIdEnumFieldPtr:
@@ -7377,6 +7439,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdMinValue:
case IrInstructionIdMaxValue:
case IrInstructionIdErrName:
+ case IrInstructionIdEmbedFile:
return false;
case IrInstructionIdAsm:
{
@@ -7390,45 +7453,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
// TODO port over all this commented out code into new IR way of doing things
-//static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,
-// BlockContext *context, AstNode *node)
-//{
-// assert(node->type == NodeTypeFnCallExpr);
-//
-// AstNode **first_param_node = &node->data.fn_call_expr.params.at(0);
-// Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node);
-// if (!rel_file_path) {
-// return g->builtin_types.entry_invalid;
-// }
-//
-// // figure out absolute path to resource
-// Buf source_dir_path = BUF_INIT;
-// os_path_dirname(import->path, &source_dir_path);
-//
-// Buf file_path = BUF_INIT;
-// os_path_resolve(&source_dir_path, rel_file_path, &file_path);
-//
-// // load from file system into const expr
-// Buf file_contents = BUF_INIT;
-// int err;
-// if ((err = os_fetch_file_path(&file_path, &file_contents))) {
-// if (err == ErrorFileNotFound) {
-// add_node_error(g, node,
-// buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
-// return g->builtin_types.entry_invalid;
-// } else {
-// add_node_error(g, node,
-// buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));
-// return g->builtin_types.entry_invalid;
-// }
-// }
-//
-// // TODO add dependency on the file we embedded so that we know if it changes
-// // we'll have to invalidate the cache
-//
-// return resolve_expr_const_val_as_string_lit(g, node, &file_contents);
-//}
-//
//static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
// BlockContext *context, AstNode *node)
//{
@@ -7765,8 +7789,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
// case BuiltinFnIdFrameAddress:
// mark_impure_fn(g, context, node);
// return builtin_fn->return_type;
-// case BuiltinFnIdEmbedFile:
-// return analyze_embed_file(g, import, context, node);
// case BuiltinFnIdCmpExchange:
// return analyze_cmpxchg(g, import, context, node);
// case BuiltinFnIdFence:
@@ -8353,7 +8375,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
// case BuiltinFnIdMinValue:
// case BuiltinFnIdMaxValue:
// case BuiltinFnIdMemberCount:
-// case BuiltinFnIdEmbedFile:
// // caught by constant expression eval codegen
// zig_unreachable();
// case BuiltinFnIdCompileVar: