Commit f833aa25 authored by Andreas Fried's avatar Andreas Fried Committed by Christoph Mallon
Browse files

Implement vararg handling in a more portable way (for now only for IA32).

This adds two builtin kinds, ir_bk_va_start and ir_bk_va_arg. va_arg Builtins
are lowered in the lower_builtins pass with a function provided by the backend,
whereby most architectures can use be_default_lower_va_args. va_start Builtins
are lowered in the backend.

Note: This commit breaks all backends except for IA32. SPARC and AMD64 are
implemented in later commits. The ARM backend previously miscompiled variadic
functions, and will now throw a proper error.
parent 7ce42e19
...@@ -78,6 +78,20 @@ typedef enum { ...@@ -78,6 +78,20 @@ typedef enum {
DW_LANG_Go = 0x0016, DW_LANG_Go = 0x0016,
} dwarf_source_language; } dwarf_source_language;
typedef void(*lower_func)(ir_node*);
/**
* This structure holds the information on how the backend implements
* variadic functions.
*/
typedef struct vararg_params {
/** Which type is to be used for va_list. If this is NULL, the
* backend does not implement variadic functions. */
ir_type *va_list_type;
/** The function to lower a call to the va_arg macro. */
lower_func lower_va_arg;
} vararg_params;
/** /**
* This structure contains parameters that should be * This structure contains parameters that should be
* propagated to the libFirm parameter set. * propagated to the libFirm parameter set.
...@@ -135,6 +149,9 @@ typedef struct backend_params { ...@@ -135,6 +149,9 @@ typedef struct backend_params {
/** Semantic on float->int conversion overflow. */ /** Semantic on float->int conversion overflow. */
float_int_conversion_overflow_style_t float_int_overflow; float_int_conversion_overflow_style_t float_int_overflow;
/** How this backend implements variadic functions. */
vararg_params vararg;
} backend_params; } backend_params;
/** /**
......
...@@ -293,7 +293,9 @@ typedef enum ir_builtin_kind { ...@@ -293,7 +293,9 @@ typedef enum ir_builtin_kind {
ir_bk_compare_swap, /**< compare exchange (aka. compare and swap) */ ir_bk_compare_swap, /**< compare exchange (aka. compare and swap) */
ir_bk_may_alias, /**< replaced by 0 if args cannot alias, ir_bk_may_alias, /**< replaced by 0 if args cannot alias,
1 otherwise */ 1 otherwise */
ir_bk_last = ir_bk_may_alias, ir_bk_va_start, /**< va_start from <stdarg.h> */
ir_bk_va_arg, /**< va_arg from <stdarg.h> */
ir_bk_last = ir_bk_va_arg,
} ir_builtin_kind; } ir_builtin_kind;
/** /**
......
...@@ -267,6 +267,7 @@ static void free_mark_proj(ir_node *node, unsigned n, pset *set) ...@@ -267,6 +267,7 @@ static void free_mark_proj(ir_node *node, unsigned n, pset *set)
case iro_Start: case iro_Start:
case iro_Alloc: case iro_Alloc:
case iro_Load: case iro_Load:
case iro_Builtin:
/* nothing: operations are handled in free_ana_walker() */ /* nothing: operations are handled in free_ana_walker() */
break; break;
......
...@@ -757,7 +757,11 @@ static backend_params amd64_backend_params = { ...@@ -757,7 +757,11 @@ static backend_params amd64_backend_params = {
.type_unsigned_long_long = NULL, /* will be set later */ .type_unsigned_long_long = NULL, /* will be set later */
.type_long_double = NULL, /* will be set later */ .type_long_double = NULL, /* will be set later */
.stack_param_align = 8, .stack_param_align = 8,
.float_int_overflow = ir_overflow_indefinite .float_int_overflow = ir_overflow_indefinite,
.vararg = {
.va_list_type = NULL,
.lower_va_arg = NULL,
},
}; };
static const backend_params *amd64_get_backend_params(void) { static const backend_params *amd64_get_backend_params(void) {
......
...@@ -1378,6 +1378,8 @@ static ir_node *gen_Builtin(ir_node *node) ...@@ -1378,6 +1378,8 @@ static ir_node *gen_Builtin(ir_node *node)
case ir_bk_saturating_increment: case ir_bk_saturating_increment:
case ir_bk_compare_swap: case ir_bk_compare_swap:
case ir_bk_may_alias: case ir_bk_may_alias:
case ir_bk_va_start:
case ir_bk_va_arg:
break; break;
} }
panic("Builtin %s not implemented", get_builtin_kind_name(kind)); panic("Builtin %s not implemented", get_builtin_kind_name(kind));
...@@ -1413,6 +1415,8 @@ static ir_node *gen_Proj_Builtin(ir_node *proj) ...@@ -1413,6 +1415,8 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
case ir_bk_saturating_increment: case ir_bk_saturating_increment:
case ir_bk_compare_swap: case ir_bk_compare_swap:
case ir_bk_may_alias: case ir_bk_may_alias:
case ir_bk_va_start:
case ir_bk_va_arg:
break; break;
} }
panic("Builtin %s not implemented", get_builtin_kind_name(kind)); panic("Builtin %s not implemented", get_builtin_kind_name(kind));
......
...@@ -276,6 +276,10 @@ static backend_params arm_backend_params = { ...@@ -276,6 +276,10 @@ static backend_params arm_backend_params = {
.type_long_double = NULL, .type_long_double = NULL,
.stack_param_align = 4, .stack_param_align = 4,
.float_int_overflow = ir_overflow_min_max, .float_int_overflow = ir_overflow_min_max,
.vararg = {
.va_list_type = NULL,
.lower_va_arg = NULL,
},
}; };
static void arm_init_backend_params(void) static void arm_init_backend_params(void)
......
/*
* This file is part of libFirm.
* Copyright (C) 2012 University of Karlsruhe.
*/
/**
* @file
* @brief Default (pointer-based) implementation of variadic functions
* @author Andreas Fried
*/
#include "bevarargs.h"
#include "be.h"
#include "bitfiddle.h"
#include "ircons.h"
#include "irgmod.h"
#include "irnode.h"
#include "util.h"
void be_default_lower_va_arg(ir_node *node)
{
ir_node *block = get_nodes_block(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_graph *irg = get_irn_irg(node);
ir_type *const aptype = get_method_res_type(get_Builtin_type(node), 0);
ir_node *const ap = get_irn_n(node, 1);
ir_node *const node_mem = get_Builtin_mem(node);
ir_mode *apmode = get_type_mode(aptype);
ir_node *res;
ir_node *new_mem;
if (apmode != NULL) {
ir_node *const load = new_rd_Load(dbgi, block, node_mem, ap, apmode, aptype, cons_none);
res = new_r_Proj(load, apmode, pn_Load_res);
new_mem = new_r_Proj(load, mode_M,pn_Load_M);
} else {
// aptype has no associated mode, so it is represented
// as a pointer.
apmode = mode_P;
res = ap;
new_mem = node_mem;
}
const backend_params *be_params = be_get_backend_param();
unsigned round_up = round_up2(get_type_size_bytes(aptype), be_params->stack_param_align);
ir_node *const diff_const = new_r_Const_long(irg, mode_Iu, round_up);
ir_node *const new_ap = new_rd_Add(dbgi, block, ap, diff_const, mode_P);
ir_node *const in[] = { new_mem, res, new_ap };
turn_into_tuple(node, ARRAY_SIZE(in), in);
}
/*
* This file is part of libFirm.
* Copyright (C) 2015 University of Karlsruhe.
*/
/**
* @file
* @brief Default (pointer-based) implementation of variadic functions
* @author Andreas Fried
*/
#ifndef FIRM_BE_BEVARARGS_H
#define FIRM_BE_BEVARARGS_H
#include "firm_types.h"
/**
* Default implementation to lower a va_arg node.
*
* This implementation assumes that all arguments are stored on the
* stack and that the va_list value points to the next variadic
* argument.
*
* @param node A Builtin node with kind ir_bk_va_arg to be lowered
*/
void be_default_lower_va_arg(ir_node *node);
#endif
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "bespillslots.h" #include "bespillslots.h"
#include "bestack.h" #include "bestack.h"
#include "beutil.h" #include "beutil.h"
#include "bevarargs.h"
#include "gen_ia32_regalloc_if.h" #include "gen_ia32_regalloc_if.h"
#include "ia32_architecture.h" #include "ia32_architecture.h"
#include "ia32_emitter.h" #include "ia32_emitter.h"
...@@ -29,6 +30,7 @@ ...@@ -29,6 +30,7 @@
#include "ia32_x87.h" #include "ia32_x87.h"
#include "ident_t.h" #include "ident_t.h"
#include "instrument.h" #include "instrument.h"
#include "ircons.h"
#include "irgmod.h" #include "irgmod.h"
#include "irgopt.h" #include "irgopt.h"
#include "irgwalk.h" #include "irgwalk.h"
...@@ -1398,6 +1400,10 @@ static backend_params ia32_backend_params = { ...@@ -1398,6 +1400,10 @@ static backend_params ia32_backend_params = {
.type_long_double = NULL, /* will be set later */ .type_long_double = NULL, /* will be set later */
.stack_param_align = 4, .stack_param_align = 4,
.float_int_overflow = ir_overflow_indefinite, .float_int_overflow = ir_overflow_indefinite,
.vararg = {
.va_list_type = NULL, /* will be set later */
.lower_va_arg = be_default_lower_va_arg,
},
}; };
/** /**
...@@ -1437,6 +1443,10 @@ static void ia32_init(void) ...@@ -1437,6 +1443,10 @@ static void ia32_init(void)
ia32_backend_params.type_long_long = type_long_long; ia32_backend_params.type_long_long = type_long_long;
ia32_backend_params.type_unsigned_long_long = type_unsigned_long_long; ia32_backend_params.type_unsigned_long_long = type_unsigned_long_long;
// va_list is a void pointer
ir_type *type_va_list = new_type_pointer(new_type_primitive(mode_ANY));
ia32_backend_params.vararg.va_list_type = type_va_list;
if (ia32_cg_config.use_sse2 || ia32_cg_config.use_softfloat) { if (ia32_cg_config.use_sse2 || ia32_cg_config.use_softfloat) {
ia32_backend_params.mode_float_arithmetic = NULL; ia32_backend_params.mode_float_arithmetic = NULL;
ia32_backend_params.type_long_double = NULL; ia32_backend_params.type_long_double = NULL;
...@@ -1557,6 +1567,7 @@ static void ia32_lower_for_target(void) ...@@ -1557,6 +1567,7 @@ static void ia32_lower_for_target(void)
supported[s++] = ir_bk_outport; supported[s++] = ir_bk_outport;
supported[s++] = ir_bk_inport; supported[s++] = ir_bk_inport;
supported[s++] = ir_bk_saturating_increment; supported[s++] = ir_bk_saturating_increment;
supported[s++] = ir_bk_va_start;
if (ia32_cg_config.use_popcnt) if (ia32_cg_config.use_popcnt)
supported[s++] = ir_bk_popcount; supported[s++] = ir_bk_popcount;
if (ia32_cg_config.use_cmpxchg) if (ia32_cg_config.use_cmpxchg)
......
...@@ -52,11 +52,13 @@ ...@@ -52,11 +52,13 @@
DEBUG_ONLY(static firm_dbg_module_t *dbg;) DEBUG_ONLY(static firm_dbg_module_t *dbg;)
static x86_cconv_t *current_cconv; static x86_cconv_t *current_cconv;
static pmap *node_to_stack; static pmap *node_to_stack;
static be_stackorder_t *stackorder; static be_stackorder_t *stackorder;
static ir_heights_t *heights; static ir_heights_t *heights;
static x86_immediate_kind_t lconst_imm_kind; static x86_immediate_kind_t lconst_imm_kind;
static ir_entity *va_start_entity;
static ir_node *initial_va_list;
/** we don't have a concept of aliasing registers, so enumerate them /** we don't have a concept of aliasing registers, so enumerate them
* manually for the asm nodes. */ * manually for the asm nodes. */
...@@ -5520,6 +5522,28 @@ static ir_node *gen_compare_swap(ir_node *node) ...@@ -5520,6 +5522,28 @@ static ir_node *gen_compare_swap(ir_node *node)
return new_node; return new_node;
} }
static ir_node *gen_va_start(ir_node *node)
{
if (initial_va_list == NULL) {
dbg_info *dbgi = get_irn_dbg_info(node);
ir_graph *irg = get_irn_irg(node);
ir_node *block = get_irg_start_block(irg);
ir_node *frame = get_irg_frame(irg);
ir_node *ap = new_bd_ia32_Lea(dbgi, block, frame, noreg_GP);
set_ia32_frame_use(ap, IA32_FRAME_USE_AUTO);
ia32_attr_t *const attr = get_ia32_attr(ap);
attr->am_imm = (x86_imm32_t){
.kind = X86_IMM_FRAMEOFFSET,
.entity = va_start_entity,
};
initial_va_list = ap;
}
return initial_va_list;
}
/** /**
* Transform Builtin node. * Transform Builtin node.
*/ */
...@@ -5558,7 +5582,10 @@ static ir_node *gen_Builtin(ir_node *node) ...@@ -5558,7 +5582,10 @@ static ir_node *gen_Builtin(ir_node *node)
return gen_saturating_increment(node); return gen_saturating_increment(node);
case ir_bk_compare_swap: case ir_bk_compare_swap:
return gen_compare_swap(node); return gen_compare_swap(node);
case ir_bk_va_start:
return gen_va_start(node);
case ir_bk_may_alias: case ir_bk_may_alias:
case ir_bk_va_arg:
break; break;
} }
panic("Builtin %s not implemented", get_builtin_kind_name(kind)); panic("Builtin %s not implemented", get_builtin_kind_name(kind));
...@@ -5606,7 +5633,18 @@ static ir_node *gen_Proj_Builtin(ir_node *proj) ...@@ -5606,7 +5633,18 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
assert(get_Proj_num(proj) == pn_Builtin_max+1); assert(get_Proj_num(proj) == pn_Builtin_max+1);
return be_new_Proj(new_node, pn_ia32_CmpXChgMem_res); return be_new_Proj(new_node, pn_ia32_CmpXChgMem_res);
} }
case ir_bk_va_start:
switch(get_Proj_num(proj)) {
case pn_Builtin_M: {
ir_node *mem = get_Builtin_mem(node);
return be_transform_node(mem);
}
case pn_Builtin_max + 1:
return new_node;
}
break;
case ir_bk_may_alias: case ir_bk_may_alias:
case ir_bk_va_arg:
break; break;
} }
panic("Builtin %s not implemented", get_builtin_kind_name(kind)); panic("Builtin %s not implemented", get_builtin_kind_name(kind));
...@@ -5771,16 +5809,17 @@ static ir_type *ia32_get_between_type(bool omit_fp) ...@@ -5771,16 +5809,17 @@ static ir_type *ia32_get_between_type(bool omit_fp)
return omit_fp ? omit_fp_between_type : between_type; return omit_fp ? omit_fp_between_type : between_type;
} }
static void ia32_create_stacklayout(ir_graph *irg, const x86_cconv_t *cconv) static void ia32_create_stacklayout(ir_graph *irg, const x86_cconv_t *cconv)
{ {
/* construct argument type */ /* construct argument type */
ir_entity *const entity = get_irg_entity(irg); ir_entity *const entity = get_irg_entity(irg);
ident *const arg_id = new_id_fmt("%s_arg_type", get_entity_ident(entity)); ident *const arg_id = new_id_fmt("%s_arg_type", get_entity_ident(entity));
ir_type *const arg_type = new_type_struct(arg_id); ir_type *const arg_type = new_type_struct(arg_id);
ir_type *const frame_type = get_irg_frame_type(irg); ir_type *const frame_type = get_irg_frame_type(irg);
size_t const n_params = cconv->n_parameters; size_t const n_params = cconv->n_parameters;
ir_entity **const param_map = ALLOCANZ(ir_entity*, n_params); ir_entity **const param_map = ALLOCANZ(ir_entity*, n_params);
ir_entity *va_start_entity = NULL;
for (size_t f = get_compound_n_members(frame_type); f-- > 0; ) { for (size_t f = get_compound_n_members(frame_type); f-- > 0; ) {
ir_entity *member = get_compound_member(frame_type, f); ir_entity *member = get_compound_member(frame_type, f);
if (!is_parameter_entity(member)) if (!is_parameter_entity(member))
...@@ -5788,13 +5827,6 @@ static void ia32_create_stacklayout(ir_graph *irg, const x86_cconv_t *cconv) ...@@ -5788,13 +5827,6 @@ static void ia32_create_stacklayout(ir_graph *irg, const x86_cconv_t *cconv)
set_entity_owner(member, arg_type); set_entity_owner(member, arg_type);
size_t num = get_entity_parameter_number(member); size_t num = get_entity_parameter_number(member);
if (num == IR_VA_START_PARAMETER_NUMBER) {
if (va_start_entity != NULL)
panic("multiple va_start entities found (%+F,%+F)",
va_start_entity, member);
va_start_entity = member;
continue;
}
assert(num < n_params); assert(num < n_params);
if (param_map[num] != NULL) if (param_map[num] != NULL)
panic("multiple entities for parameter %u in %+F found", f, irg); panic("multiple entities for parameter %u in %+F found", f, irg);
...@@ -5813,9 +5845,15 @@ static void ia32_create_stacklayout(ir_graph *irg, const x86_cconv_t *cconv) ...@@ -5813,9 +5845,15 @@ static void ia32_create_stacklayout(ir_graph *irg, const x86_cconv_t *cconv)
param->entity = entity; param->entity = entity;
set_entity_offset(param->entity, param->offset); set_entity_offset(param->entity, param->offset);
} }
if (va_start_entity != NULL) {
ir_type *const function_type = get_entity_type(entity);
if (is_method_variadic(function_type)) {
ir_type *unknown = get_unknown_type();
va_start_entity = new_parameter_entity(arg_type, IR_VA_START_PARAMETER_NUMBER, unknown);
set_entity_offset(va_start_entity, cconv->callframe_size); set_entity_offset(va_start_entity, cconv->callframe_size);
} }
set_type_size_bytes(arg_type, cconv->callframe_size); set_type_size_bytes(arg_type, cconv->callframe_size);
be_stack_layout_t *const layout = be_get_irg_stack_layout(irg); be_stack_layout_t *const layout = be_get_irg_stack_layout(irg);
...@@ -5885,6 +5923,7 @@ void ia32_transform_graph(ir_graph *irg) ...@@ -5885,6 +5923,7 @@ void ia32_transform_graph(ir_graph *irg)
x86_free_calling_convention(current_cconv); x86_free_calling_convention(current_cconv);
pmap_destroy(node_to_stack); pmap_destroy(node_to_stack);
node_to_stack = NULL; node_to_stack = NULL;
initial_va_list = NULL;
} }
void ia32_init_transform(void) void ia32_init_transform(void)
......
...@@ -535,6 +535,10 @@ static const backend_params *sparc_get_backend_params(void) ...@@ -535,6 +535,10 @@ static const backend_params *sparc_get_backend_params(void)
.type_long_double = NULL, /* will be set later */ .type_long_double = NULL, /* will be set later */
.stack_param_align = 4, .stack_param_align = 4,
.float_int_overflow = ir_overflow_min_max, .float_int_overflow = ir_overflow_min_max,
.vararg = {
.va_list_type = NULL,
.lower_va_arg = NULL,
},
}; };
ir_mode *mode_long_long ir_mode *mode_long_long
......
...@@ -2099,6 +2099,8 @@ static ir_node *gen_Builtin(ir_node *node) ...@@ -2099,6 +2099,8 @@ static ir_node *gen_Builtin(ir_node *node)
case ir_bk_saturating_increment: case ir_bk_saturating_increment:
return gen_saturating_increment(node); return gen_saturating_increment(node);
case ir_bk_may_alias: case ir_bk_may_alias:
case ir_bk_va_start:
case ir_bk_va_arg:
break; break;
} }
panic("Builtin %s not implemented", get_builtin_kind_name(kind)); panic("Builtin %s not implemented", get_builtin_kind_name(kind));
...@@ -2141,6 +2143,8 @@ static ir_node *gen_Proj_Builtin(ir_node *proj) ...@@ -2141,6 +2143,8 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
return be_new_Proj(new_pred, pn_sparc_Cas_res); return be_new_Proj(new_pred, pn_sparc_Cas_res);
} }
case ir_bk_may_alias: case ir_bk_may_alias:
case ir_bk_va_start:
case ir_bk_va_arg:
break; break;
} }
panic("Builtin %s not implemented", get_builtin_kind_name(kind)); panic("Builtin %s not implemented", get_builtin_kind_name(kind));
......
...@@ -570,6 +570,8 @@ const char *get_builtin_kind_name(ir_builtin_kind kind) ...@@ -570,6 +570,8 @@ const char *get_builtin_kind_name(ir_builtin_kind kind)
X(ir_bk_saturating_increment); X(ir_bk_saturating_increment);
X(ir_bk_compare_swap); X(ir_bk_compare_swap);
X(ir_bk_may_alias); X(ir_bk_may_alias);
X(ir_bk_va_start);
X(ir_bk_va_arg);
} }
return "<unknown>"; return "<unknown>";
#undef X #undef X
...@@ -826,6 +828,8 @@ int is_irn_const_memory(const ir_node *node) ...@@ -826,6 +828,8 @@ int is_irn_const_memory(const ir_node *node)
case ir_bk_trap: case ir_bk_trap:
case ir_bk_debugbreak: case ir_bk_debugbreak:
case ir_bk_compare_swap: case ir_bk_compare_swap:
case ir_bk_va_start:
case ir_bk_va_arg:
return false; return false;
case ir_bk_return_address: case ir_bk_return_address:
case ir_bk_frame_address: case ir_bk_frame_address:
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include "adt/pmap.h" #include "adt/pmap.h"
#include "be.h"
#include "irnode_t.h" #include "irnode_t.h"
#include "ircons_t.h" #include "ircons_t.h"
#include "irgmod.h" #include "irgmod.h"
...@@ -42,6 +43,8 @@ static const char *get_builtin_name(ir_builtin_kind kind) ...@@ -42,6 +43,8 @@ static const char *get_builtin_name(ir_builtin_kind kind)
case ir_bk_saturating_increment: case ir_bk_saturating_increment:
case ir_bk_compare_swap: case ir_bk_compare_swap:
case ir_bk_may_alias: case ir_bk_may_alias:
case ir_bk_va_start:
case ir_bk_va_arg:
break; break;
} }
abort(); abort();
...@@ -145,6 +148,10 @@ changed: ...@@ -145,6 +148,10 @@ changed:
*changed = true; *changed = true;
return; return;
case ir_bk_va_arg:
be_get_backend_param()->vararg.lower_va_arg(node);
return;
case ir_bk_trap: case ir_bk_trap:
case ir_bk_debugbreak: case ir_bk_debugbreak:
case ir_bk_return_address: case ir_bk_return_address:
...@@ -153,6 +160,7 @@ changed: ...@@ -153,6 +160,7 @@ changed:
case ir_bk_outport: case ir_bk_outport:
case ir_bk_saturating_increment: case ir_bk_saturating_increment:
case ir_bk_compare_swap: case ir_bk_compare_swap:
case ir_bk_va_start:
/* can't do anything about these, backend will probably fail now */ /* can't do anything about these, backend will probably fail now */
panic("cannot lower Builtin node of kind %+F", node); panic("cannot lower Builtin node of kind %+F", node);
} }
...@@ -168,6 +176,7 @@ void lower_builtins(size_t n_exceptions, ir_builtin_kind *exceptions) ...@@ -168,6 +176,7 @@ void lower_builtins(size_t n_exceptions, ir_builtin_kind *exceptions)
foreach_irp_irg(i, irg) { foreach_irp_irg(i, irg) {
bool changed = false; bool changed = false;
assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES);
irg_walk_graph(irg, NULL, lower_builtin, &changed); irg_walk_graph(irg, NULL, lower_builtin, &changed);
confirm_irg_properties(irg, changed ? IR_GRAPH_PROPERTIES_CONTROL_FLOW confirm_irg_properties(irg, changed ? IR_GRAPH_PROPERTIES_CONTROL_FLOW
: IR_GRAPH_PROPERTIES_ALL); : IR_GRAPH_PROPERTIES_ALL);
......
...@@ -2424,6 +2424,8 @@ static void lower_Builtin(ir_node *builtin, ir_mode *mode) ...@@ -2424,6 +2424,8 @@ static void lower_Builtin(ir_node *builtin, ir_mode *mode)
case ir_bk_return_address: case ir_bk_return_address:
case ir_bk_saturating_increment: case ir_bk_saturating_increment:
case ir_bk_trap: case ir_bk_trap:
case ir_bk_va_start:
case ir_bk_va_arg:
/* Nothing to do/impossible to lower in a generic way */ /* Nothing to do/impossible to lower in a generic way */
return; return;
case ir_bk_bswap: case ir_bk_bswap:
......