aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-10-02 22:00:42 -0400
committerAndrew Kelley <superjoe30@gmail.com>2017-10-03 00:29:27 -0400
commitf1bd02e6f46821415d96f54f6a3258159ba5a9c5 (patch)
treeb9ccd45ba8b9aa047ae2ba4dc071f219167a2aa9 /src/ir.cpp
parentc180ef86afee17e36135b653fb6256cff46f4e69 (diff)
downloadzig-f1bd02e6f46821415d96f54f6a3258159ba5a9c5.tar.gz
zig-f1bd02e6f46821415d96f54f6a3258159ba5a9c5.zip
add @setAlignStack builtin
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 422c40b678..570783872f 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -563,6 +563,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
return IrInstructionIdOpaqueType;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionSetAlignStack *) {
+ return IrInstructionIdSetAlignStack;
+}
+
template<typename T>
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -2248,6 +2252,17 @@ static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *align_bytes)
+{
+ IrInstructionSetAlignStack *instruction = ir_build_instruction<IrInstructionSetAlignStack>(irb, scope, source_node);
+ instruction->align_bytes = align_bytes;
+
+ ir_ref_instruction(align_bytes, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
return nullptr;
}
@@ -2970,6 +2985,13 @@ static IrInstruction *ir_instruction_opaquetype_get_dep(IrInstructionOpaqueType
return nullptr;
}
+static IrInstruction *ir_instruction_setalignstack_get_dep(IrInstructionSetAlignStack *instruction, size_t index) {
+ switch (index) {
+ case 0: return instruction->align_bytes;
+ default: return nullptr;
+ }
+}
+
static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -3170,6 +3192,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_aligncast_get_dep((IrInstructionAlignCast *) instruction, index);
case IrInstructionIdOpaqueType:
return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index);
+ case IrInstructionIdSetAlignStack:
+ return ir_instruction_setalignstack_get_dep((IrInstructionSetAlignStack *) instruction, index);
}
zig_unreachable();
}
@@ -4596,6 +4620,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
case BuiltinFnIdOpaqueType:
return ir_build_opaque_type(irb, scope, node);
+ case BuiltinFnIdSetAlignStack:
+ {
+ 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_set_align_stack(irb, scope, node, arg0_value);
+ }
}
zig_unreachable();
}
@@ -15264,6 +15297,41 @@ static TypeTableEntry *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInst
return ira->codegen->builtin_types.entry_type;
}
+static TypeTableEntry *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstructionSetAlignStack *instruction) {
+ uint32_t align_bytes;
+ IrInstruction *align_bytes_inst = instruction->align_bytes->other;
+ if (!ir_resolve_align(ira, align_bytes_inst, &align_bytes))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ if (fn_entry == nullptr) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack outside function"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ if (fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionNaked) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack in naked function"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ if (fn_entry->fn_inline == FnInlineAlways) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack in inline function"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ if (fn_entry->set_alignstack_node != nullptr) {
+ ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
+ buf_sprintf("alignstack set twice"));
+ add_error_note(ira->codegen, msg, fn_entry->set_alignstack_node, buf_sprintf("first set here"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ fn_entry->set_alignstack_node = instruction->base.source_node;
+ fn_entry->alignstack_value = align_bytes;
+
+ ir_build_const_from(ira, &instruction->base);
+ return ira->codegen->builtin_types.entry_void;
+}
+
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -15452,6 +15520,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
case IrInstructionIdOpaqueType:
return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
+ case IrInstructionIdSetAlignStack:
+ return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction);
}
zig_unreachable();
}
@@ -15564,6 +15634,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPanic:
case IrInstructionIdSetEvalBranchQuota:
case IrInstructionIdPtrTypeOf:
+ case IrInstructionIdSetAlignStack:
return true;
case IrInstructionIdPhi:
case IrInstructionIdUnOp: