authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-28 02:32:36-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-28 02:32:36-04:00
log8e2804efa1d23696a476ab3f88c6b9852370cf8b
treeadd9fdc7bc0fd6b3ba1d0832a30efeaebc6a8451
parent114049a22031be63da511ea53f4e655fc72a4578

IR: ability to assign to an array at runtime


3 files changed, 126 insertions(+), 77 deletions(-)

src/codegen.cpp+31-3
...@@ -2857,18 +2857,45 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -2857,18 +2857,45 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
2857}2857}
28582858
2859static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) {2859static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) {
2860 return LLVMBuildLoad(g->builder, ir_llvm_value(g, instruction->ptr), "");2860 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
2861 return get_handle_value(g, ptr, instruction->base.type_entry);
2861}2862}
28622863
2863static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {2864static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
2864 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);2865 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
2865 LLVMValueRef value = ir_llvm_value(g, instruction->value);2866 LLVMValueRef value = ir_llvm_value(g, instruction->value);
2867
2868 assert(instruction->ptr->type_entry->id == TypeTableEntryIdPointer);
2869 TypeTableEntry *op1_type = instruction->ptr->type_entry->data.pointer.child_type;
2870 TypeTableEntry *op2_type = instruction->value->type_entry;
2871
2872 if (!type_has_bits(op1_type)) {
2873 return nullptr;
2874 }
2875 if (handle_is_ptr(op1_type)) {
2876 assert(op1_type == op2_type);
2877 return gen_struct_memcpy(g, value, ptr, op1_type);
2878 }
2879
2866 LLVMBuildStore(g->builder, value, ptr);2880 LLVMBuildStore(g->builder, value, ptr);
2867 return nullptr;2881 return nullptr;
2868}2882}
28692883
2870static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {2884static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
2871 return instruction->var->value_ref;2885 VariableTableEntry *var = instruction->var;
2886 if (type_has_bits(var->type)) {
2887 assert(var->value_ref);
2888 return get_handle_value(g, var->value_ref, var->type);
2889 } else {
2890 return nullptr;
2891 }
2892}
2893
2894static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) {
2895 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array_ptr);
2896 LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index);
2897 TypeTableEntry *array_type = instruction->array_ptr->type_entry;
2898 return gen_array_elem_ptr(g, instruction->base.source_node, array_ptr, array_type, subscript_value);
2872}2899}
28732900
2874static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {2901static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
...@@ -2942,6 +2969,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2942,6 +2969,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2942 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);2969 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
2943 case IrInstructionIdVarPtr:2970 case IrInstructionIdVarPtr:
2944 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);2971 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
2972 case IrInstructionIdElemPtr:
2973 return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);
2945 case IrInstructionIdCall:2974 case IrInstructionIdCall:
2946 return ir_render_call(g, executable, (IrInstructionCall *)instruction);2975 return ir_render_call(g, executable, (IrInstructionCall *)instruction);
2947 case IrInstructionIdSwitchBr:2976 case IrInstructionIdSwitchBr:
...@@ -2950,7 +2979,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2950,7 +2979,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2950 case IrInstructionIdContainerInitList:2979 case IrInstructionIdContainerInitList:
2951 case IrInstructionIdContainerInitFields:2980 case IrInstructionIdContainerInitFields:
2952 case IrInstructionIdFieldPtr:2981 case IrInstructionIdFieldPtr:
2953 case IrInstructionIdElemPtr:
2954 zig_panic("TODO render more IR instructions to LLVM");2982 zig_panic("TODO render more IR instructions to LLVM");
2955 }2983 }
2956 zig_unreachable();2984 zig_unreachable();
src/ir.cpp+94-74
...@@ -30,7 +30,8 @@ struct IrAnalyze {...@@ -30,7 +30,8 @@ struct IrAnalyze {
30};30};
3131
32static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);32static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
33static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope, LValPurpose purpose);33static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
34 LValPurpose lval);
3435
35static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {36static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
36 assert(basic_block);37 assert(basic_block);
...@@ -334,6 +335,27 @@ static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_i...@@ -334,6 +335,27 @@ static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_i
334335
335}336}
336337
338static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, AstNode *source_node, IrInstruction *array_ptr,
339 IrInstruction *elem_index)
340{
341 IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, source_node);
342 instruction->array_ptr = array_ptr;
343 instruction->elem_index = elem_index;
344
345 ir_ref_instruction(array_ptr);
346 ir_ref_instruction(elem_index);
347
348 return &instruction->base;
349}
350
351static IrInstruction *ir_build_elem_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
352 IrInstruction *array_ptr, IrInstruction *elem_index)
353{
354 IrInstruction *new_instruction = ir_build_elem_ptr(irb, old_instruction->source_node, array_ptr, elem_index);
355 ir_link_new_instruction(new_instruction, old_instruction);
356 return new_instruction;
357}
358
337static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,359static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
338 IrInstruction *fn, size_t arg_count, IrInstruction **args)360 IrInstruction *fn, size_t arg_count, IrInstruction **args)
339{361{
...@@ -677,7 +699,7 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op...@@ -677,7 +699,7 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op
677}699}
678700
679static IrInstruction *ir_gen_assign(IrBuilder *irb, AstNode *node) {701static IrInstruction *ir_gen_assign(IrBuilder *irb, AstNode *node) {
680 IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign);702 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign);
681 if (lvalue == irb->codegen->invalid_instruction)703 if (lvalue == irb->codegen->invalid_instruction)
682 return lvalue;704 return lvalue;
683705
...@@ -690,7 +712,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, AstNode *node) {...@@ -690,7 +712,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, AstNode *node) {
690}712}
691713
692static IrInstruction *ir_gen_assign_op(IrBuilder *irb, AstNode *node, IrBinOp op_id) {714static IrInstruction *ir_gen_assign_op(IrBuilder *irb, AstNode *node, IrBinOp op_id) {
693 IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign);715 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign);
694 if (lvalue == irb->codegen->invalid_instruction)716 if (lvalue == irb->codegen->invalid_instruction)
695 return lvalue;717 return lvalue;
696 IrInstruction *op1 = ir_build_load_ptr(irb, node->data.bin_op_expr.op1, lvalue);718 IrInstruction *op1 = ir_build_load_ptr(irb, node->data.bin_op_expr.op1, lvalue);
...@@ -882,6 +904,26 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose l...@@ -882,6 +904,26 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose l
882 return irb->codegen->invalid_instruction;904 return irb->codegen->invalid_instruction;
883}905}
884906
907static IrInstruction *ir_gen_array_access(IrBuilder *irb, AstNode *node, LValPurpose lval) {
908 assert(node->type == NodeTypeArrayAccessExpr);
909
910 AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;
911 IrInstruction *array_ref_instruction = ir_gen_node(irb, array_ref_node, node->block_context);
912 if (array_ref_instruction == irb->codegen->invalid_instruction)
913 return array_ref_instruction;
914
915 AstNode *subscript_node = node->data.array_access_expr.subscript;
916 IrInstruction *subscript_instruction = ir_gen_node(irb, subscript_node, node->block_context);
917 if (subscript_instruction == irb->codegen->invalid_instruction)
918 return subscript_instruction;
919
920 IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, node, array_ref_instruction, subscript_instruction);
921 if (lval != LValPurposeNone)
922 return ptr_instruction;
923
924 return ir_build_load_ptr(irb, node, ptr_instruction);
925}
926
885static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {927static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
886 assert(node->type == NodeTypeFnCallExpr);928 assert(node->type == NodeTypeFnCallExpr);
887929
...@@ -1151,7 +1193,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {...@@ -1151,7 +1193,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {
1151 return ir_build_const_void(irb, node);1193 return ir_build_const_void(irb, node);
1152}1194}
11531195
1154static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, LValPurpose lval) {1196static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
1197 LValPurpose lval)
1198{
1155 assert(block_context);1199 assert(block_context);
1156 node->block_context = block_context;1200 node->block_context = block_context;
11571201
...@@ -1176,10 +1220,11 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont...@@ -1176,10 +1220,11 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
1176 return ir_gen_var_decl(irb, node);1220 return ir_gen_var_decl(irb, node);
1177 case NodeTypeWhileExpr:1221 case NodeTypeWhileExpr:
1178 return ir_gen_while_expr(irb, node);1222 return ir_gen_while_expr(irb, node);
1223 case NodeTypeArrayAccessExpr:
1224 return ir_gen_array_access(irb, node, lval);
1179 case NodeTypeUnwrapErrorExpr:1225 case NodeTypeUnwrapErrorExpr:
1180 case NodeTypeReturnExpr:1226 case NodeTypeReturnExpr:
1181 case NodeTypeDefer:1227 case NodeTypeDefer:
1182 case NodeTypeArrayAccessExpr:
1183 case NodeTypeSliceExpr:1228 case NodeTypeSliceExpr:
1184 case NodeTypeFieldAccessExpr:1229 case NodeTypeFieldAccessExpr:
1185 case NodeTypeIfVarExpr:1230 case NodeTypeIfVarExpr:
...@@ -1223,67 +1268,6 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *s...@@ -1223,67 +1268,6 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *s
1223 return ir_gen_node_extra(irb, node, scope, LValPurposeNone);1268 return ir_gen_node_extra(irb, node, scope, LValPurposeNone);
1224}1269}
12251270
1226static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope, LValPurpose lval) {
1227 assert(scope);
1228 node->block_context = scope;
1229 switch (node->type) {
1230 case NodeTypeSymbol:
1231 return ir_gen_symbol(irb, node, lval);
1232 case NodeTypeArrayAccessExpr:
1233 zig_panic("TODO array access lvalue");
1234 case NodeTypeFieldAccessExpr:
1235 zig_panic("TODO field access lvalue");
1236 case NodeTypePrefixOpExpr:
1237 zig_panic("TODO prefix op lvalue");
1238 case NodeTypeBlock:
1239 case NodeTypeBinOpExpr:
1240 case NodeTypeNumberLiteral:
1241 case NodeTypeFnCallExpr:
1242 case NodeTypeIfBoolExpr:
1243 case NodeTypeContainerInitExpr:
1244 case NodeTypeVariableDeclaration:
1245 case NodeTypeWhileExpr:
1246 case NodeTypeUnwrapErrorExpr:
1247 case NodeTypeReturnExpr:
1248 case NodeTypeDefer:
1249 case NodeTypeSliceExpr:
1250 case NodeTypeIfVarExpr:
1251 case NodeTypeForExpr:
1252 case NodeTypeAsmExpr:
1253 case NodeTypeGoto:
1254 case NodeTypeBreak:
1255 case NodeTypeContinue:
1256 case NodeTypeLabel:
1257 case NodeTypeSwitchExpr:
1258 case NodeTypeBoolLiteral:
1259 case NodeTypeStringLiteral:
1260 case NodeTypeCharLiteral:
1261 case NodeTypeNullLiteral:
1262 case NodeTypeUndefinedLiteral:
1263 case NodeTypeZeroesLiteral:
1264 case NodeTypeThisLiteral:
1265 case NodeTypeErrorType:
1266 case NodeTypeTypeLiteral:
1267 case NodeTypeArrayType:
1268 case NodeTypeVarLiteral:
1269 case NodeTypeRoot:
1270 case NodeTypeFnProto:
1271 case NodeTypeFnDef:
1272 case NodeTypeFnDecl:
1273 case NodeTypeParamDecl:
1274 case NodeTypeUse:
1275 case NodeTypeContainerDecl:
1276 case NodeTypeStructField:
1277 case NodeTypeStructValueField:
1278 case NodeTypeSwitchProng:
1279 case NodeTypeSwitchRange:
1280 case NodeTypeErrorValueDecl:
1281 case NodeTypeTypeDecl:
1282 zig_unreachable();
1283 }
1284 zig_unreachable();
1285}
1286
1287IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {1271IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
1288 assert(node->owner);1272 assert(node->owner);
12891273
...@@ -4034,6 +4018,46 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct...@@ -4034,6 +4018,46 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
4034 return ptr_type;4018 return ptr_type;
4035}4019}
40364020
4021static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
4022 IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other;
4023 IrInstruction *elem_index = elem_ptr_instruction->elem_index->other;
4024
4025 TypeTableEntry *array_type = array_ptr->type_entry;
4026 TypeTableEntry *return_type;
4027
4028 if (array_type->id == TypeTableEntryIdInvalid) {
4029 return array_type;
4030 } else if (array_type->id == TypeTableEntryIdArray) {
4031 if (array_type->data.array.len == 0) {
4032 add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
4033 buf_sprintf("out of bounds array access"));
4034 }
4035 TypeTableEntry *child_type = array_type->data.array.child_type;
4036 return_type = get_pointer_to_type(ira->codegen, child_type, false);
4037 } else if (array_type->id == TypeTableEntryIdPointer) {
4038 return_type = array_type;
4039 } else if (is_slice(array_type)) {
4040 return_type = array_type->data.structure.fields[0].type_entry;
4041 } else {
4042 add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
4043 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
4044 return ira->codegen->builtin_types.entry_invalid;
4045 }
4046
4047 TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize;
4048 IrInstruction *casted_elem_index = ir_get_casted_value(ira, elem_index, usize);
4049 if (casted_elem_index == ira->codegen->invalid_instruction)
4050 return ira->codegen->builtin_types.entry_invalid;
4051
4052 if (array_ptr->static_value.ok && casted_elem_index->static_value.ok) {
4053 zig_panic("TODO compile time array access");
4054 }
4055
4056 ir_build_elem_ptr_from(&ira->new_irb, &elem_ptr_instruction->base, array_ptr, casted_elem_index);
4057
4058 return return_type;
4059}
4060
4037static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {4061static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
4038 IrInstruction *ptr = load_ptr_instruction->ptr->other;4062 IrInstruction *ptr = load_ptr_instruction->ptr->other;
4039 TypeTableEntry *type_entry = ptr->type_entry;4063 TypeTableEntry *type_entry = ptr->type_entry;
...@@ -4125,7 +4149,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -4125,7 +4149,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
4125 case IrInstructionIdFieldPtr:4149 case IrInstructionIdFieldPtr:
4126 zig_panic("TODO field ptr");4150 zig_panic("TODO field ptr");
4127 case IrInstructionIdElemPtr:4151 case IrInstructionIdElemPtr:
4128 zig_panic("TODO elem ptr");4152 return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction);
4129 case IrInstructionIdVarPtr:4153 case IrInstructionIdVarPtr:
4130 return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);4154 return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);
4131 case IrInstructionIdCall:4155 case IrInstructionIdCall:
...@@ -4149,16 +4173,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -4149,16 +4173,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
4149 zig_unreachable();4173 zig_unreachable();
4150}4174}
41514175
4152static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction,4176static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) {
4153 TypeTableEntry *expected_type)
4154{
4155 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);4177 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
4156 instruction->type_entry = instruction_type;4178 instruction->type_entry = instruction_type;
4157 if (instruction->other)4179 if (instruction->other)
4158 instruction->other->type_entry = instruction_type;4180 instruction->other->type_entry = instruction_type;
41594181 return instruction_type;
4160 IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type);
4161 return casted_instruction->type_entry;
4162}4182}
41634183
4164// This function attempts to evaluate IR code while doing type checking and other analysis.4184// This function attempts to evaluate IR code while doing type checking and other analysis.
...@@ -4195,7 +4215,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -4195,7 +4215,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
4195 continue;4215 continue;
4196 }4216 }
41974217
4198 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction, nullptr);4218 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction);
41994219
4200 // unreachable instructions do their own control flow.4220 // unreachable instructions do their own control flow.
4201 if (return_type->id == TypeTableEntryIdUnreachable)4221 if (return_type->id == TypeTableEntryIdUnreachable)
src/ir_print.cpp+1
...@@ -320,6 +320,7 @@ static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruc...@@ -320,6 +320,7 @@ static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruc
320}320}
321321
322static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) {322static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) {
323 fprintf(irp->f, "&");
323 ir_print_other_instruction(irp, instruction->array_ptr);324 ir_print_other_instruction(irp, instruction->array_ptr);
324 fprintf(irp->f, "[");325 fprintf(irp->f, "[");
325 ir_print_other_instruction(irp, instruction->elem_index);326 ir_print_other_instruction(irp, instruction->elem_index);