format_check.c \
lexer.c \
main.c \
+ mangle.c \
walk_statements.c \
symbol_table.c \
token.c \
fputs(") ", out);
}
+static void print_scope(const scope_t *scope)
+{
+ const entity_t *entity = scope->entities;
+ for ( ; entity != NULL; entity = entity->base.next) {
+ print_indent();
+ print_entity(entity);
+ fputs("\n", out);
+ }
+}
+
+static void print_namespace(const namespace_t *namespace)
+{
+ fputs("namespace ", out);
+ if (namespace->base.symbol != NULL) {
+ fputs(namespace->base.symbol->string, out);
+ fputc(' ', out);
+ }
+
+ fputs("{\n", out);
+ ++indent;
+
+ print_scope(&namespace->members);
+
+ --indent;
+ print_indent();
+ fputs("}\n", out);
+}
+
/**
* Print a variable or function declaration
*/
switch ((entity_kind_tag_t) entity->kind) {
case ENTITY_VARIABLE:
- case ENTITY_FUNCTION:
case ENTITY_COMPOUND_MEMBER:
print_declaration(entity);
return;
+ case ENTITY_FUNCTION:
+ print_declaration(entity);
+ return;
case ENTITY_TYPEDEF:
print_typedef(entity);
return;
print_enum_definition(&entity->enume);
fputc(';', out);
return;
+ case ENTITY_NAMESPACE:
+ print_namespace(&entity->namespacee);
+ return;
case ENTITY_LABEL:
case ENTITY_ENUM_VALUE:
case ENTITY_LOCAL_LABEL:
#include "diagnostic.h"
#include "lang_features.h"
#include "types.h"
+#include "type_hash.h"
+#include "mangle.h"
#include "walk_statements.h"
#include "warning.h"
#include "entitymap_t.h"
#include "driver/firm_opt.h"
#include "driver/firm_cmdline.h"
-/* some idents needed for name mangling */
-static ident *id_underscore;
-static ident *id_imp;
-
static ir_type *ir_type_const_char;
static ir_type *ir_type_wchar_t;
static ir_type *ir_type_void;
static entity_t **inner_functions;
static ir_node *ijmp_list;
static bool constant_folding;
+static symbol_t *sym_C;
extern bool have_const_functions;
static ir_node *current_funcsig;
static switch_statement_t *current_switch;
static ir_graph *current_function;
+static translation_unit_t *current_translation_unit;
static entitymap_t entitymap;
DECLARATION_KIND_INNER_FUNCTION
} declaration_kind_t;
-static ir_type *get_ir_type(type_t *type);
+static ir_mode *get_ir_mode(type_t *type);
static ir_type *get_ir_type_incomplete(type_t *type);
static void enqueue_inner_function(entity_t *entity)
static ir_node *_expression_to_firm(const expression_t *expression);
static ir_node *expression_to_firm(const expression_t *expression);
-static inline ir_mode *get_ir_mode(type_t *type);
static void create_local_declaration(entity_t *entity);
static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
set_method_variadicity(irtype, variadicity_variadic);
}
+#if 0
+ /* TODO: revive this with linkage stuff */
unsigned cc = get_method_calling_convention(irtype);
switch (function_type->calling_convention) {
case CC_DEFAULT: /* unspecified calling convention, equal to one of the other, typically cdecl */
/* Hmm, leave default, not accepted by the parser yet. */
break;
}
+#endif
+
return irtype;
}
snprintf(name, sizeof(name), "I%u", size);
ident *id = new_id_from_str(name);
dbg_info *dbgi = get_dbg_info(&builtin_source_position);
- res = new_d_type_primitive(mangle_u(get_type_ident(base_tp), id), mode, dbgi);
+ res = new_d_type_primitive(id_mangle_u(get_type_ident(base_tp), id), mode, dbgi);
set_primitive_base_type(res, base_tp);
return res;
snprintf(name, sizeof(name), "U%u", size);
ident *id = new_id_from_str(name);
dbg_info *dbgi = get_dbg_info(&builtin_source_position);
- res = new_d_type_primitive(mangle_u(get_type_ident(base_tp), id), mode, dbgi);
+ res = new_d_type_primitive(id_mangle_u(get_type_ident(base_tp), id), mode, dbgi);
set_primitive_base_type(res, base_tp);
return res;
}
}
-static ir_type *get_ir_type(type_t *type)
+ir_type *get_ir_type(type_t *type)
{
assert(type != NULL);
return firm_type;
}
-static inline ir_mode *get_ir_mode(type_t *type)
+ir_mode *get_ir_mode(type_t *type)
{
ir_type *irtype = get_ir_type(type);
static ident *rts_idents[sizeof(rts_data) / sizeof(rts_data[0])];
-/**
- * Mangles an entity linker (ld) name for win32 usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-static ident *create_ld_ident_win32(ir_entity *irentity, entity_t *entity)
-{
- ident *id;
-
- if (is_Method_type(get_entity_type(irentity)))
- id = decorate_win32_c_fkt(irentity, get_entity_ident(irentity));
- else {
- /* always add an underscore in win32 */
- id = mangle(id_underscore, get_entity_ident(irentity));
- }
-
- assert(is_declaration(entity));
- decl_modifiers_t decl_modifiers = entity->declaration.modifiers;
- if (decl_modifiers & DM_DLLIMPORT) {
- /* add prefix for imported symbols */
- id = mangle(id_imp, id);
- }
- return id;
-}
-
-/**
- * Mangles an entity linker (ld) name for Linux ELF usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-static ident *create_ld_ident_linux_elf(ir_entity *irentity, entity_t *entity)
-{
- (void) entity;
- return get_entity_ident(irentity);
-}
-
-/**
- * Mangles an entity linker (ld) name for Mach-O usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-static ident *create_ld_ident_macho(ir_entity *irentity, entity_t *entity)
-{
- (void) entity;
- ident *id = mangle(id_underscore, get_entity_ident(irentity));
- return id;
-}
-
-typedef ident* (*create_ld_ident_func)(ir_entity *irentity, entity_t *entity);
-create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf;
+typedef ident* (*create_ld_ident_func)(entity_t *entity);
+create_ld_ident_func create_ld_ident = create_name_linux_elf;
/**
* Handle GNU attributes for entities
}
}
+static bool is_main(entity_t *entity)
+{
+ static symbol_t *sym_main = NULL;
+ if (sym_main == NULL) {
+ sym_main = symbol_table_insert("main");
+ }
+
+ if (entity->base.symbol != sym_main)
+ return false;
+ /* must be in outermost scope */
+ if (entity->base.parent_scope != ¤t_translation_unit->scope)
+ return false;
+
+ return true;
+}
+
/**
* Creates an entity representing a function.
*
return entity->function.entity;
}
+ if (is_main(entity)) {
+ /* force main to C linkage */
+ type_t *type = entity->declaration.type;
+ assert(is_type_function(type));
+ if (type->function.linkage != NULL && type->function.linkage != sym_C) {
+ errorf(&entity->base.source_position,
+ "main must have \"C\" linkage");
+ }
+
+ if (type->function.linkage == NULL || type->function.linkage != sym_C) {
+ type_t *new_type = duplicate_type(type);
+ new_type->function.linkage = sym_C;
+
+ type = typehash_insert(new_type);
+ if (type != new_type) {
+ obstack_free(type_obst, new_type);
+ }
+ entity->declaration.type = type;
+ }
+ }
+
symbol_t *symbol = entity->base.symbol;
ident *id = new_id_from_str(symbol->string);
dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
irentity = new_d_entity(global_type, id, ir_type_method, dbgi);
- set_entity_ld_ident(irentity, create_ld_ident(irentity, entity));
+ set_entity_ld_ident(irentity, create_ld_ident(entity));
handle_gnu_attributes_ent(irentity, entity);
variable->declaration.kind = (unsigned char) declaration_kind;
variable->variable.v.entity = irentity;
set_entity_variability(irentity, variability_uninitialized);
- set_entity_ld_ident(irentity, create_ld_ident(irentity, variable));
+ set_entity_ld_ident(irentity, create_ld_ident(variable));
if (parent_type == get_tls_type())
set_entity_allocation(irentity, allocation_automatic);
else if (declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE)
entity->declaration.kind = DECLARATION_KIND_GLOBAL_VARIABLE;
entity->variable.v.entity = irentity;
- set_entity_ld_ident(irentity, create_ld_ident(irentity, entity));
+ set_entity_ld_ident(irentity, id);
set_entity_variability(irentity, variability_uninitialized);
set_entity_visibility(irentity, visibility_local);
set_entity_allocation(irentity, allocation_static);
ir_node *in[1];
/* ยง5.1.2.2.3 main implicitly returns 0 */
- if (strcmp(entity->base.symbol->string, "main") == 0) {
+ if (is_main(entity)) {
in[0] = new_Const(mode, get_mode_null(mode));
} else {
in[0] = new_Unknown(mode);
obstack_init(&asm_obst);
init_atomic_modes();
- id_underscore = new_id_from_chars("_", 1);
- id_imp = new_id_from_chars("__imp_", 6);
-
/* OS option must be set to the backend */
switch (firm_opt.os_support) {
case OS_SUPPORT_MINGW:
- create_ld_ident = create_ld_ident_win32;
+ create_ld_ident = create_name_win32;
break;
case OS_SUPPORT_LINUX:
- create_ld_ident = create_ld_ident_linux_elf;
+ create_ld_ident = create_name_linux_elf;
break;
case OS_SUPPORT_MACHO:
- create_ld_ident = create_ld_ident_macho;
+ create_ld_ident = create_name_macho;
break;
+ default:
+ panic("unexpected OS support mode");
}
/* create idents for all known runtime functions */
rts_idents[i] = new_id_from_str(rts_data[i].name);
}
+ sym_C = symbol_table_insert("C");
+
entitymap_init(&entitymap);
}
void translation_unit_to_firm(translation_unit_t *unit)
{
/* just to be sure */
- continue_label = NULL;
- break_label = NULL;
- current_switch_cond = NULL;
+ continue_label = NULL;
+ break_label = NULL;
+ current_switch_cond = NULL;
+ current_translation_unit = unit;
init_ir_types();
inner_functions = NEW_ARR_F(entity_t *, 0);
DEL_ARR_F(inner_functions);
inner_functions = NULL;
- current_ir_graph = NULL;
+ current_ir_graph = NULL;
+ current_translation_unit = NULL;
}
void exit_ast2firm(void);
ir_mode *get_atomic_mode(atomic_type_kind_t kind);
+ir_type *get_ir_type(type_t *type);
#endif
#include "symbol.h"
#include "token_t.h"
#include "type.h"
-#include "entity.h"
+#include "entity_t.h"
#include "adt/obst.h"
/** The AST obstack contains all data that must stay in the AST. */
EXPR_UNARY_CASES_MANDATORY \
EXPR_UNARY_CASES_OPTIONAL
-/**
- * A scope containing declarations.
- */
-struct scope_t {
- entity_t *entities; /**< List of declarations in this scope. */
- entity_t *last_entity; /**< last declaration in this scope. */
- scope_t *parent; /**< points to the parent scope. */
- unsigned depth; /**< while parsing, the depth of this scope in the scope stack. */
-};
-
struct expression_base_t {
expression_kind_t kind;
type_t *type;
for (i = 0; i < get_irp_n_irgs(); i++) {
ir_graph *irg = get_irp_irg(i);
-#ifdef FIRM_EXT_GRS
- /* If SIMD optimization is on, make sure we have only 1 return */
- if (firm_ext_grs.create_pattern || firm_ext_grs.simd_opt)
- do_irg_opt("onereturn");
-#endif
-
do_irg_opt(irg, "scalar");
do_irg_opt(irg, "local");
do_irg_opt(irg, "reassoc");
params.cc_mask = 0; /* no regparam, cdecl */
params.builtin_dbg = NULL;
- #ifdef FIRM_EXT_GRS
- /* Activate Graph rewriting if SIMD optimization is turned on */
- /* This has to be done before init_firm() is called! */
- if (firm_ext_grs.simd_opt)
- ext_grs_activate();
-#endif
-
init_firm(¶ms);
if (firm_be_opt.selection == BE_FIRM_BE) {
if (be_params->has_imm_fp_mode)
firm_imm_fp_mode = be_params->imm_fp_mode;
}
- /* OS option must be set to the backend */
- switch (firm_opt.os_support) {
- case OS_SUPPORT_MINGW:
- firm_be_option("ia32-gasmode=mingw");
- break;
- case OS_SUPPORT_MACHO:
- firm_be_option("ia32-gasmode=macho");
- break;
- case OS_SUPPORT_LINUX:
- default:
- firm_be_option("ia32-gasmode=linux");
- break;
- }
dbg_init(NULL, NULL, dbg_snprint);
edges_init_dbg(firm_opt.vrfy_edges);
- //cbackend_set_debug_retrieve(dbg_retrieve);
set_opt_precise_exc_context(firm_opt.precise_exc);
set_opt_fragile_ops(firm_opt.fragile_ops);
for (i = get_irp_n_irgs() - 1; i >= 0; --i)
set_irg_phase_low(get_irp_irg(i));
-
-#ifdef FIRM_EXT_GRS
- /** SIMD Optimization Extensions **/
-
- /* Pattern creation step. No code has to be generated, so
- exit after pattern creation */
- if (firm_ext_grs.create_pattern) {
- ext_grs_create_pattern();
- exit(0);
- }
-
- /* SIMD optimization step. Uses graph patterns to find
- rich instructions and rewrite */
- if (firm_ext_grs.simd_opt)
- ext_grs_simd_opt();
-#endif
-
if (firm_dump.statistic & STAT_FINAL_IR)
stat_dump_snapshot(input_filename, "final-ir");
if (firm_dump.statistic & STAT_FINAL)
stat_dump_snapshot(input_filename, "final");
-
-#if 0
- if (firm_opt.ycomp_dbg)
- firm_finish_ycomp_debugger();
-#endif
-} /* gen_firm_finish */
+}
/**
* Do very early initializations
*/
-void firm_early_init(void) {
+void firm_early_init(void)
+{
/* arg: need this here for command line options */
be_opt_register();
firm_init_options(NULL, 0, NULL);
-} /* firm_early_init */
+}
typedef struct enum_t enum_t;
typedef struct enum_value_t enum_value_t;
typedef struct label_t label_t;
+typedef struct namespace_t namespace_t;
typedef struct declaration_t declaration_t;
typedef struct typedef_t typedef_t;
typedef struct variable_t variable_t;
#ifndef ENTITY_T_H
#define ENTITY_T_H
+#include "lexer.h"
+#include "symbol.h"
#include "entity.h"
typedef enum {
ENTITY_ENUM,
ENTITY_ENUM_VALUE,
ENTITY_LABEL,
- ENTITY_LOCAL_LABEL
+ ENTITY_LOCAL_LABEL,
+ ENTITY_NAMESPACE
} entity_kind_tag_t;
typedef unsigned char entity_kind_t;
NAMESPACE_ENUM,
NAMESPACE_LABEL
} namespace_tag_t;
-typedef unsigned char namespace_t;
+typedef unsigned char entity_namespace_t;
typedef enum storage_class_tag_t {
STORAGE_CLASS_NONE,
typedef unsigned decl_modifiers_t;
+/**
+ * A scope containing entities.
+ */
+struct scope_t {
+ entity_t *entities;
+ entity_t *last_entity;
+ scope_t *parent; /**< points to the parent scope. */
+ unsigned depth; /**< while parsing, the depth of this scope in the
+ scope stack. */
+};
+
/**
* a named entity is something which can be referenced by its name
* (a symbol)
*/
struct entity_base_t {
entity_kind_t kind;
- namespace_t namespc;
+ entity_namespace_t namespc;
symbol_t *symbol;
source_position_t source_position;
scope_t *parent_scope; /**< The parent scope where this declaration lives. */
ir_node *block;
};
+struct namespace_t {
+ entity_base_t base;
+ scope_t members;
+};
+
struct typedef_t {
entity_base_t base;
decl_modifiers_t modifiers;
enum_t enume;
enum_value_t enum_value;
label_t label;
+ namespace_t namespacee;
typedef_t typedefe;
declaration_t declaration;
variable_t variable;
#define HAVE_MKSTEMP
#endif
-#ifndef WITH_LIBCORE
-#define WITH_LIBCORE
-#endif
-
#include <libfirm/firm.h>
#include <libfirm/be.h>
#include "write_caml.h"
#include "revision.h"
#include "warning.h"
+#include "mangle.h"
#ifndef PREPROCESSOR
#ifdef __APPLE__
/** we have extern function with const attribute. */
bool have_const_functions = false;
+atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
+
/* to switch on printing of implicit casts */
extern bool print_implicit_casts;
init_ast();
init_parser();
init_ast2firm();
+ init_mangle();
if (construct_dep_target) {
if (outname != 0 && strlen(outname) >= 2) {
obstack_free(&ldflags_obst, NULL);
obstack_free(&file_obst, NULL);
+ exit_mangle();
exit_ast2firm();
exit_parser();
exit_ast();
--- /dev/null
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <config.h>
+
+#include <libfirm/firm.h>
+#include <string.h>
+
+#include "entity_t.h"
+#include "type_t.h"
+#include "symbol_t.h"
+#include "mangle.h"
+#include "diagnostic.h"
+#include "ast2firm.h"
+#include "lang_features.h"
+#include "adt/error.h"
+
+static ident *id_underscore;
+static ident *id_imp;
+static symbol_t *sym_C;
+static symbol_t *sym_stdcall;
+static struct obstack obst;
+
+static void mangle_type(type_t *type);
+
+static const char *get_atomic_type_mangle(atomic_type_kind_t kind)
+{
+ switch (kind) {
+ case ATOMIC_TYPE_INVALID: break;
+ case ATOMIC_TYPE_VOID: return "v";
+ case ATOMIC_TYPE_BOOL: return "b";
+ case ATOMIC_TYPE_CHAR: return "c";
+ case ATOMIC_TYPE_SCHAR: return "a";
+ case ATOMIC_TYPE_UCHAR: return "h";
+ case ATOMIC_TYPE_INT: return "i";
+ case ATOMIC_TYPE_UINT: return "j";
+ case ATOMIC_TYPE_SHORT: return "s";
+ case ATOMIC_TYPE_USHORT: return "t";
+ case ATOMIC_TYPE_LONG: return "l";
+ case ATOMIC_TYPE_ULONG: return "m";
+ case ATOMIC_TYPE_LONGLONG: return "x";
+ case ATOMIC_TYPE_ULONGLONG: return "y";
+ case ATOMIC_TYPE_LONG_DOUBLE: return "e";
+ case ATOMIC_TYPE_FLOAT: return "f";
+ case ATOMIC_TYPE_DOUBLE: return "d";
+ }
+ panic("invalid atomic type in mangler");
+}
+
+static void mangle_atomic_type(const atomic_type_t *type)
+{
+ obstack_printf(&obst, "%s", get_atomic_type_mangle(type->akind));
+}
+
+static void mangle_pointer_type(const pointer_type_t *type)
+{
+ obstack_printf(&obst, "P");
+ mangle_type(type->points_to);
+}
+
+static void mangle_function_type(const function_type_t *type)
+{
+ obstack_printf(&obst, "F");
+ if (type->linkage == sym_C) {
+ obstack_printf(&obst, "Y");
+ }
+
+ mangle_type(type->return_type);
+
+ function_parameter_t *parameter = type->parameters;
+ for ( ; parameter != NULL; parameter = parameter->next) {
+ mangle_type(parameter->type);
+ }
+ if (type->variadic) {
+ obstack_printf(&obst, "z");
+ }
+ if (type->unspecified_parameters)
+ panic("can't mangle unspecified parameter types");
+ if (type->kr_style_parameters)
+ panic("can't mangle kr_style_parameters type");
+
+ obstack_printf(&obst, "E");
+}
+
+static void mangle_qualifiers(type_qualifiers_t qualifiers)
+{
+ if (qualifiers & TYPE_QUALIFIER_CONST)
+ obstack_printf(&obst, "K");
+ if (qualifiers & TYPE_QUALIFIER_VOLATILE)
+ obstack_printf(&obst, "V");
+ if (qualifiers & TYPE_QUALIFIER_RESTRICT)
+ obstack_printf(&obst, "r");
+
+ /* handle MS extended qualifiers? */
+}
+
+static void mangle_type(type_t *orig_type)
+{
+ type_t *type = skip_typeref(orig_type);
+
+ mangle_qualifiers(type->base.qualifiers);
+
+ switch (type->kind) {
+ case TYPE_ATOMIC:
+ mangle_atomic_type(&type->atomic);
+ return;
+ case TYPE_POINTER:
+ mangle_pointer_type(&type->pointer);
+ return;
+ case TYPE_FUNCTION:
+ mangle_function_type(&type->function);
+ return;
+ case TYPE_INVALID:
+ panic("invalid type encountered while mangling");
+ case TYPE_ERROR:
+ panic("error type encountered while mangling");
+ case TYPE_BUILTIN:
+ case TYPE_TYPEDEF:
+ case TYPE_TYPEOF:
+ panic("typeref not resolved while manging?!?");
+
+ case TYPE_BITFIELD:
+ case TYPE_COMPLEX:
+ case TYPE_IMAGINARY:
+ case TYPE_COMPOUND_STRUCT:
+ case TYPE_COMPOUND_UNION:
+ case TYPE_ENUM:
+ case TYPE_ARRAY:
+ panic("no mangling for this type implemented yet");
+ break;
+ }
+ panic("invalid type encountered while mangling");
+}
+
+
+/**
+ * Mangles an entity linker (ld) name for win32 usage.
+ *
+ * @param ent the entity to be mangled
+ * @param declaration the declaration
+ */
+ident *create_name_win32(entity_t *entity)
+{
+ ident *id = new_id_from_str(entity->base.symbol->string);
+
+ if (entity->kind == ENTITY_FUNCTION) {
+ if (entity->declaration.type->function.linkage == sym_stdcall) {
+ char buf[16];
+ ir_type *irtype = get_ir_type(entity->declaration.type);
+ size_t size = 0;
+ for (int i = get_method_n_params(irtype) - 1; i >= 0; --i) {
+ size += get_type_size_bytes(get_method_param_type(irtype, i));
+ }
+
+ snprintf(buf, sizeof(buf), "@%d", size);
+ return id_mangle3("_", id, buf);
+ }
+ } else {
+ /* always add an underscore in win32 */
+ id = id_mangle(id_underscore, id);
+ }
+
+ assert(is_declaration(entity));
+ decl_modifiers_t decl_modifiers = entity->declaration.modifiers;
+ if (decl_modifiers & DM_DLLIMPORT) {
+ /* add prefix for imported symbols */
+ id = id_mangle(id_imp, id);
+ }
+ return id;
+}
+
+static void mangle_entity(entity_t *entity)
+{
+ assert(obstack_object_size(&obst) == 0);
+ obstack_printf(&obst, "_Z");
+
+ /* TODO: mangle scope */
+
+ symbol_t *symbol = entity->base.symbol;
+ obstack_printf(&obst, "%u%s", strlen(symbol->string), symbol->string);
+
+ if (entity->kind == ENTITY_FUNCTION) {
+ mangle_type(entity->declaration.type);
+ }
+}
+
+/**
+ * Mangles an entity linker (ld) name for Linux ELF usage.
+ *
+ * @param ent the entity to be mangled
+ * @param declaration the declaration
+ */
+ident *create_name_linux_elf(entity_t *entity)
+{
+ bool needs_mangling = false;
+
+ if (entity->kind == ENTITY_FUNCTION && (c_mode & _CXX)) {
+ symbol_t *linkage = entity->declaration.type->function.linkage;
+
+ if (linkage == NULL) {
+ needs_mangling = true;
+ } else if (linkage != sym_C) {
+ errorf(&entity->base.source_position,
+ "Unknown linkage type \"%Y\" found\n", linkage);
+ }
+ }
+
+ if (needs_mangling) {
+ mangle_entity(entity);
+ obstack_1grow(&obst, '\0');
+ char *str = obstack_finish(&obst);
+
+ ident *id = new_id_from_str(str);
+ obstack_free(&obst, str);
+
+ return id;
+ }
+
+ return new_id_from_str(entity->base.symbol->string);
+}
+
+/**
+ * Mangles an entity linker (ld) name for Mach-O usage.
+ *
+ * @param ent the entity to be mangled
+ * @param declaration the declaration
+ */
+ident *create_name_macho(entity_t *entity)
+{
+ ident *id = new_id_from_str(entity->base.symbol->string);
+ return id_mangle(id_underscore, id);
+}
+
+void init_mangle(void)
+{
+ id_underscore = new_id_from_chars("_", 1);
+ id_imp = new_id_from_chars("__imp_", 6);
+ sym_C = symbol_table_insert("C");
+ sym_stdcall = symbol_table_insert("stdcall");
+
+ obstack_init(&obst);
+}
+
+void exit_mangle(void)
+{
+ obstack_free(&obst, NULL);
+}
--- /dev/null
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef MANGLE_H
+#define MANGLE_H
+
+#include "entity.h"
+#include <libfirm/firm_types.h>
+
+ident *create_name_linux_elf(entity_t *entity);
+ident *create_name_macho(entity_t *entity);
+ident *create_name_win32(entity_t *entity);
+
+void init_mangle(void);
+void exit_mangle(void);
+
+#endif
#define MAX_LOOKAHEAD 2
typedef struct {
- entity_t *old_entity;
- symbol_t *symbol;
- namespace_t namespc;
+ entity_t *old_entity;
+ symbol_t *symbol;
+ entity_namespace_t namespc;
} stack_entry_t;
typedef struct argument_list_t argument_list_t;
static int lookahead_bufpos;
static stack_entry_t *environment_stack = NULL;
static stack_entry_t *label_stack = NULL;
-/** The global file scope. */
static scope_t *file_scope = NULL;
-/** The current scope. */
-static scope_t *scope = NULL;
+static scope_t *current_scope = NULL;
/** Point to the current function declaration if inside a function. */
static function_t *current_function = NULL;
static entity_t *current_init_decl = NULL;
static statement_t *current_loop = NULL;
static statement_t *current_parent = NULL;
static ms_try_statement_t *current_try = NULL;
+static symbol_t *current_linkage = NULL;
static goto_statement_t *goto_first = NULL;
static goto_statement_t *goto_last = NULL;
static label_statement_t *label_first = NULL;
static expression_t *parse_sub_expression(precedence_t);
static expression_t *parse_expression(void);
static type_t *parse_typename(void);
+static void parse_externals(void);
+static void parse_external(void);
static void parse_compound_type_entries(compound_t *compound_declaration);
static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
case T_register: \
case T___thread:
+#define STORAGE_CLASSES_NO_EXTERN \
+ case T_typedef: \
+ case T_static: \
+ case T_auto: \
+ case T_register: \
+ case T___thread:
+
#define TYPE_QUALIFIERS \
case T_const: \
case T_restrict: \
TYPE_QUALIFIERS \
TYPE_SPECIFIERS
+#define DECLARATION_START_NO_EXTERN \
+ STORAGE_CLASSES_NO_EXTERN \
+ TYPE_QUALIFIERS \
+ TYPE_SPECIFIERS
+
#define TYPENAME_START \
TYPE_QUALIFIERS \
TYPE_SPECIFIERS
[ENTITY_ENUM] = sizeof(enum_t),
[ENTITY_ENUM_VALUE] = sizeof(enum_value_t),
[ENTITY_LABEL] = sizeof(label_t),
- [ENTITY_LOCAL_LABEL] = sizeof(label_t)
+ [ENTITY_LOCAL_LABEL] = sizeof(label_t),
+ [ENTITY_NAMESPACE] = sizeof(namespace_t)
};
assert(kind < sizeof(sizes) / sizeof(sizes[0]));
assert(sizes[kind] != 0);
static void scope_push(scope_t *new_scope)
{
- if (scope != NULL) {
- new_scope->depth = scope->depth + 1;
+ if (current_scope != NULL) {
+ new_scope->depth = current_scope->depth + 1;
}
- new_scope->parent = scope;
- scope = new_scope;
+ new_scope->parent = current_scope;
+ current_scope = new_scope;
}
static void scope_pop(void)
{
- scope = scope->parent;
+ current_scope = current_scope->parent;
}
/**
* Search an entity by its symbol in a given namespace.
*/
-static entity_t *get_entity(const symbol_t *const symbol, namespace_t namespc)
+static entity_t *get_entity(const symbol_t *const symbol,
+ namespace_tag_t namespc)
{
entity_t *entity = symbol->entity;
for( ; entity != NULL; entity = entity->base.symbol_next) {
*/
static void stack_push(stack_entry_t **stack_ptr, entity_t *entity)
{
- symbol_t *symbol = entity->base.symbol;
- namespace_t namespc = entity->base.namespc;
+ symbol_t *symbol = entity->base.symbol;
+ entity_namespace_t namespc = entity->base.namespc;
assert(namespc != NAMESPACE_INVALID);
/* replace/add entity into entity list of the symbol */
for(i = top; i > new_top; --i) {
stack_entry_t *entry = &stack[i - 1];
- entity_t *old_entity = entry->old_entity;
- symbol_t *symbol = entry->symbol;
- namespace_t namespc = entry->namespc;
+ entity_t *old_entity = entry->old_entity;
+ symbol_t *symbol = entry->symbol;
+ entity_namespace_t namespc = entry->namespc;
/* replace with old_entity/remove */
entity_t **anchor;
symbol = token.v.symbol;
next_token();
- namespace_t const namespc =
+ namespace_tag_t const namespc =
is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION;
entity_t *entity = get_entity(symbol, namespc);
if (entity != NULL) {
assert(entity->kind == (is_struct ? ENTITY_STRUCT : ENTITY_UNION));
compound = &entity->compound;
- if (compound->base.parent_scope != scope &&
+ if (compound->base.parent_scope != current_scope &&
(token.type == '{' || token.type == ';')) {
/* we're in an inner scope and have a definition. Override
existing definition in outer scope */
(is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION);
compound->base.source_position = token.source_position;
compound->base.symbol = symbol;
- compound->base.parent_scope = scope;
+ compound->base.parent_scope = current_scope;
if (symbol != NULL) {
environment_push(entity);
}
- append_entity(scope, entity);
+ append_entity(current_scope, entity);
}
if (token.type == '{') {
entity->base.namespc = NAMESPACE_ENUM;
entity->base.source_position = token.source_position;
entity->base.symbol = symbol;
- entity->base.parent_scope = scope;
+ entity->base.parent_scope = current_scope;
}
type_t *const type = allocate_type_zero(TYPE_ENUM);
if (symbol != NULL) {
environment_push(entity);
}
- append_entity(scope, entity);
+ append_entity(current_scope, entity);
entity->enume.complete = true;
parse_enum_entries(type);
{
type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ type->function.linkage = current_linkage;
+
/* TODO: revive this... once we know exactly how to do it */
#if 0
decl_modifiers_t modifiers = entity->declaration.modifiers;
storage_class_t storage_class = specifiers->storage_class;
entity->declaration.declared_storage_class = storage_class;
- if (storage_class == STORAGE_CLASS_NONE && scope != file_scope) {
+ if (storage_class == STORAGE_CLASS_NONE
+ && current_scope != file_scope) {
storage_class = STORAGE_CLASS_AUTO;
}
entity->declaration.storage_class = storage_class;
return strcmp(sym->string, "main") == 0;
}
+static const char *get_entity_kind_name(entity_kind_t kind)
+{
+ switch ((entity_kind_tag_t) kind) {
+ case ENTITY_FUNCTION: return "function";
+ case ENTITY_VARIABLE: return "variable";
+ case ENTITY_COMPOUND_MEMBER: return "compound type member";
+ case ENTITY_STRUCT: return "struct";
+ case ENTITY_UNION: return "union";
+ case ENTITY_ENUM: return "enum";
+ case ENTITY_ENUM_VALUE: return "enum value";
+ case ENTITY_LABEL: return "label";
+ case ENTITY_LOCAL_LABEL: return "local label";
+ case ENTITY_TYPEDEF: return "typedef";
+ case ENTITY_NAMESPACE: return "namespace";
+ case ENTITY_INVALID: break;
+ }
+
+ panic("Invalid entity kind encountered in get_entity_kind_name");
+}
+
+static void error_redefined_as_different_kind(const source_position_t *pos,
+ const entity_t *old, entity_kind_t new_kind)
+{
+ errorf(pos, "redeclaration of %s '%Y' as %s (declared %P)",
+ get_entity_kind_name(old->kind), old->base.symbol, new_kind,
+ &old->base.source_position);
+}
+
/**
* record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
* for various problems that occur for multiple definitions
static entity_t *record_entity(entity_t *entity, const bool is_definition)
{
const symbol_t *const symbol = entity->base.symbol;
- const namespace_t namespc = entity->base.namespc;
+ const namespace_tag_t namespc = entity->base.namespc;
const source_position_t *pos = &entity->base.source_position;
assert(symbol != NULL);
orig_type, symbol);
}
- if (warning.main && scope == file_scope && is_sym_main(symbol)) {
+ if (warning.main && current_scope == file_scope
+ && is_sym_main(symbol)) {
check_type_of_main(entity);
}
}
if (is_declaration(entity)) {
if (warning.nested_externs
&& entity->declaration.storage_class == STORAGE_CLASS_EXTERN
- && scope != file_scope) {
+ && current_scope != file_scope) {
warningf(pos, "nested extern declaration of '%#T'",
entity->declaration.type, symbol);
}
if (previous_entity != NULL
&& previous_entity->base.parent_scope == ¤t_function->parameters
- && scope->depth == previous_entity->base.parent_scope->depth + 1) {
+ && current_scope->depth == previous_entity->base.parent_scope->depth+1){
assert(previous_entity->kind == ENTITY_VARIABLE);
errorf(pos,
}
if (previous_entity != NULL
- && previous_entity->base.parent_scope == scope) {
+ && previous_entity->base.parent_scope == current_scope) {
if (previous_entity->kind != entity->kind) {
- errorf(pos,
- "redeclaration of '%Y' as different kind of symbol (declared %P)",
- symbol, &previous_entity->base.source_position);
+ error_redefined_as_different_kind(pos, previous_entity,
+ entity->kind);
goto finish;
}
if (previous_entity->kind == ENTITY_ENUM_VALUE) {
}
} else if (warning.missing_declarations
&& entity->kind == ENTITY_VARIABLE
- && scope == file_scope) {
+ && current_scope == file_scope) {
declaration_t *declaration = &entity->declaration;
if (declaration->storage_class == STORAGE_CLASS_NONE ||
declaration->storage_class == STORAGE_CLASS_THREAD) {
finish:
assert(entity->base.parent_scope == NULL);
- assert(scope != NULL);
+ assert(current_scope != NULL);
- entity->base.parent_scope = scope;
+ entity->base.parent_scope = current_scope;
entity->base.namespc = NAMESPACE_NORMAL;
environment_push(entity);
- append_entity(scope, entity);
+ append_entity(current_scope, entity);
return entity;
}
assert(entity->base.namespc == NAMESPACE_NORMAL);
entity_t *previous_entity = get_entity(symbol, NAMESPACE_NORMAL);
if (previous_entity == NULL
- || previous_entity->base.parent_scope != scope) {
+ || previous_entity->base.parent_scope != current_scope) {
errorf(HERE, "expected declaration of a function parameter, found '%Y'",
symbol);
return entity;
entity_t *parameter = entity->function.parameters.entities;
for ( ; parameter != NULL; parameter = parameter->base.next) {
assert(parameter->base.parent_scope == NULL);
- parameter->base.parent_scope = scope;
+ parameter->base.parent_scope = current_scope;
environment_push(parameter);
}
}
/* pop function parameters */
- assert(scope == &entity->function.parameters);
+ assert(current_scope == &entity->function.parameters);
scope_pop();
environment_pop_to(top);
}
assert(is_declaration(ndeclaration));
- type_t *type = ndeclaration->declaration.type;
+ type_t *type = skip_typeref(ndeclaration->declaration.type);
- /* note that we don't skip typerefs: the standard doesn't allow them here
- * (so we can't use is_type_function here) */
- if (type->kind != TYPE_FUNCTION) {
+ if (!is_type_function(type)) {
if (is_type_valid(type)) {
errorf(HERE, "declarator '%#T' has a body but is not a function type",
type, ndeclaration->base.symbol);
entity_t *parameter = function->parameters.entities;
for( ; parameter != NULL; parameter = parameter->base.next) {
if (parameter->base.parent_scope == &ndeclaration->function.parameters) {
- parameter->base.parent_scope = scope;
+ parameter->base.parent_scope = current_scope;
}
assert(parameter->base.parent_scope == NULL
- || parameter->base.parent_scope == scope);
- parameter->base.parent_scope = scope;
+ || parameter->base.parent_scope == current_scope);
+ parameter->base.parent_scope = current_scope;
if (parameter->base.symbol == NULL) {
errorf(¶meter->base.source_position, "parameter name omitted");
continue;
label_pop_to(label_stack_top);
}
- assert(scope == &function->parameters);
+ assert(current_scope == &function->parameters);
scope_pop();
environment_pop_to(top);
}
label = get_entity(symbol, NAMESPACE_LABEL);
/* if we found a local label, we already created the declaration */
if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) {
- if (label->base.parent_scope != scope) {
- assert(label->base.parent_scope->depth < scope->depth);
+ if (label->base.parent_scope != current_scope) {
+ assert(label->base.parent_scope->depth < current_scope->depth);
current_function->goto_to_outer = true;
}
return &label->label;
rem_anchor_token(')');
statement->fors.body = parse_loop_body(statement);
- assert(scope == &statement->fors.scope);
+ assert(current_scope == &statement->fors.scope);
scope_pop();
environment_pop_to(top);
end_error:
POP_PARENT;
rem_anchor_token(')');
- assert(scope == &statement->fors.scope);
+ assert(current_scope == &statement->fors.scope);
scope_pop();
environment_pop_to(top);
mark_vars_read(return_value, NULL);
}
- const type_t *const func_type = current_function->base.type;
+ const type_t *const func_type = skip_typeref(current_function->base.type);
assert(is_type_function(func_type));
type_t *const return_type = skip_typeref(func_type->function.return_type);
{
statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION);
- entity_t *before = scope->last_entity;
+ entity_t *before = current_scope->last_entity;
if (GNU_MODE)
parse_external_declaration();
else
parse_declaration(record_entity);
if (before == NULL) {
- statement->declaration.declarations_begin = scope->entities;
+ statement->declaration.declarations_begin = current_scope->entities;
} else {
statement->declaration.declarations_begin = before->base.next;
}
- statement->declaration.declarations_end = scope->last_entity;
+ statement->declaration.declarations_end = current_scope->last_entity;
return statement;
}
}
symbol_t *symbol = token.v.symbol;
entity_t *entity = get_entity(symbol, NAMESPACE_LABEL);
- if (entity != NULL && entity->base.parent_scope == scope) {
+ if (entity != NULL && entity->base.parent_scope == current_scope) {
errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition %P)",
symbol, &entity->base.source_position);
} else {
entity = allocate_entity_zero(ENTITY_LOCAL_LABEL);
- entity->base.parent_scope = scope;
+ entity->base.parent_scope = current_scope;
entity->base.namespc = NAMESPACE_LABEL;
entity->base.source_position = token.source_position;
entity->base.symbol = symbol;
return statement;
}
+static void parse_namespace_definition(void)
+{
+ eat(T_namespace);
+
+ entity_t *entity = NULL;
+ symbol_t *symbol = NULL;
+
+ if (token.type == T_IDENTIFIER) {
+ symbol = token.v.symbol;
+ next_token();
+
+ entity = get_entity(symbol, NAMESPACE_NORMAL);
+ if (entity != NULL && entity->kind != ENTITY_NAMESPACE
+ && entity->base.parent_scope == current_scope) {
+ error_redefined_as_different_kind(&token.source_position,
+ entity, ENTITY_NAMESPACE);
+ entity = NULL;
+ }
+ }
+
+ if (entity == NULL) {
+ entity = allocate_entity_zero(ENTITY_NAMESPACE);
+ entity->base.symbol = symbol;
+ entity->base.source_position = token.source_position;
+ entity->base.namespc = NAMESPACE_NORMAL;
+ entity->base.parent_scope = current_scope;
+ }
+
+ if (token.type == '=') {
+ /* TODO: parse namespace alias */
+ panic("namespace alias definition not supported yet");
+ }
+
+ environment_push(entity);
+ append_entity(current_scope, entity);
+
+ size_t const top = environment_top();
+ scope_push(&entity->namespacee.members);
+
+ expect('{');
+ parse_externals();
+ expect('}');
+
+end_error:
+ assert(current_scope == &entity->namespacee.members);
+ scope_pop();
+ environment_pop_to(top);
+}
+
/**
* Parse a statement.
* There's also parse_statement() which additionally checks for
statement = parse_local_label_declaration();
break;
- case ';': statement = parse_empty_statement(); break;
- case '{': statement = parse_compound_statement(false); break;
- case T___leave: statement = parse_leave_statement(); break;
- case T___try: statement = parse_ms_try_statment(); break;
- case T_asm: statement = parse_asm_statement(); break;
- case T_break: statement = parse_break(); break;
- case T_case: statement = parse_case_statement(); break;
- case T_continue: statement = parse_continue(); break;
- case T_default: statement = parse_default_statement(); break;
- case T_do: statement = parse_do(); break;
- case T_for: statement = parse_for(); break;
- case T_goto: statement = parse_goto(); break;
- case T_if: statement = parse_if(); break;
- case T_return: statement = parse_return(); break;
- case T_switch: statement = parse_switch(); break;
- case T_while: statement = parse_while(); break;
+ case ';': statement = parse_empty_statement(); break;
+ case '{': statement = parse_compound_statement(false); break;
+ case T___leave: statement = parse_leave_statement(); break;
+ case T___try: statement = parse_ms_try_statment(); break;
+ case T_asm: statement = parse_asm_statement(); break;
+ case T_break: statement = parse_break(); break;
+ case T_case: statement = parse_case_statement(); break;
+ case T_continue: statement = parse_continue(); break;
+ case T_default: statement = parse_default_statement(); break;
+ case T_do: statement = parse_do(); break;
+ case T_for: statement = parse_for(); break;
+ case T_goto: statement = parse_goto(); break;
+ case T_if: statement = parse_if(); break;
+ case T_return: statement = parse_return(); break;
+ case T_switch: statement = parse_switch(); break;
+ case T_while: statement = parse_while(); break;
EXPRESSION_START
statement = parse_expression_statement();
end_error:
rem_anchor_token('}');
- assert(scope == &statement->compound.scope);
+ assert(current_scope == &statement->compound.scope);
scope_pop();
environment_pop_to(top);
end_error:;
}
-/**
- * Parse a translation unit.
- */
-static void parse_translation_unit(void)
+static void parse_linkage_specification(void)
{
+ eat(T_extern);
+ assert(token.type == T_STRING_LITERAL);
+
+ string_t linkage = parse_string_literals();
+ /* convert to symbol for easier handling... */
+ symbol_t *symbol = symbol_table_insert(linkage.begin);
+
+
+ symbol_t *old_linkage = current_linkage;
+ current_linkage = symbol;
+
+ if (token.type == '{') {
+ next_token();
+ parse_externals();
+ expect('}');
+ } else {
+ parse_external();
+ }
+
+end_error:
+ assert(current_linkage == symbol);
+ current_linkage = old_linkage;
+}
+
+static void parse_external(void)
+{
+ switch (token.type) {
+ DECLARATION_START_NO_EXTERN
+ case T_IDENTIFIER:
+ case T___extension__:
+ case '(': /* for function declarations with implicit return type and
+ * parenthesized declarator, i.e. (f)(void); */
+ parse_external_declaration();
+ return;
+
+ case T_extern:
+ if (look_ahead(1)->type == T_STRING_LITERAL) {
+ parse_linkage_specification();
+ } else {
+ parse_external_declaration();
+ }
+ return;
+
+ case T_asm:
+ parse_global_asm();
+ return;
+
+ case T_namespace:
+ parse_namespace_definition();
+ return;
+
+ case ';':
+ if (!strict_mode) {
+ if (warning.other)
+ warningf(HERE, "stray ';' outside of function");
+ next_token();
+ return;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ errorf(HERE, "stray %K outside of function", &token);
+ if (token.type == '(' || token.type == '{' || token.type == '[')
+ eat_until_matching_token(token.type);
+ next_token();
+ return;
+ }
+}
+
+static void parse_externals(void)
+{
+ add_anchor_token('}');
add_anchor_token(T_EOF);
#ifndef NDEBUG
unsigned char token_anchor_copy[T_LAST_TOKEN];
memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy));
#endif
- for (;;) {
+
+ while (token.type != T_EOF && token.type != '}') {
#ifndef NDEBUG
bool anchor_leak = false;
for (int i = 0; i != T_LAST_TOKEN; ++i) {
abort();
#endif
- switch (token.type) {
- DECLARATION_START
- case T_IDENTIFIER:
- case T___extension__:
- case '(': /* for function declarations with implicit return type and
- * parenthesized declarator, i.e. (f)(void); */
- parse_external_declaration();
- break;
+ parse_external();
+ }
- case T_asm:
- parse_global_asm();
- break;
+ rem_anchor_token(T_EOF);
+ rem_anchor_token('}');
+}
- case T_EOF:
- rem_anchor_token(T_EOF);
- return;
+/**
+ * Parse a translation unit.
+ */
+static void parse_translation_unit(void)
+{
+ add_anchor_token(T_EOF);
- case ';':
- if (!strict_mode) {
- if (warning.other)
- warningf(HERE, "stray ';' outside of function");
- next_token();
- break;
- }
- /* FALLTHROUGH */
+ while (true) {
+ parse_externals();
- default:
- errorf(HERE, "stray %K outside of function", &token);
- if (token.type == '(' || token.type == '{' || token.type == '[')
- eat_until_matching_token(token.type);
- next_token();
- break;
- }
+ if (token.type == T_EOF)
+ break;
+
+ errorf(HERE, "stray %K outside of function", &token);
+ if (token.type == '(' || token.type == '{' || token.type == '[')
+ eat_until_matching_token(token.type);
+ next_token();
}
}
assert(file_scope == NULL);
file_scope = &unit->scope;
- assert(scope == NULL);
+ assert(current_scope == NULL);
scope_push(&unit->scope);
}
translation_unit_t *finish_parsing(void)
{
/* do NOT use scope_pop() here, this will crash, will it by hand */
- assert(scope == &unit->scope);
- scope = NULL;
+ assert(current_scope == &unit->scope);
+ current_scope = NULL;
assert(file_scope == &unit->scope);
check_unused_globals();
static void print_spaces(void)
{
- if (counted_newlines >= 8) {
+ if (counted_newlines >= 9) {
if (input.had_non_space) {
fputc('\n', out);
}
#endif
#define S(mode, x, val) T(mode, x, #x, val)
-S(_ANSI|_C99, signed, )
-S(_ALL, __signed, = T_signed)
-S(_ALL, __signed__, = T_signed)
-S(_C99|_GNUC, _Complex, )
-S(_ALL, __complex__, = T__Complex)
-S(_ALL, __complex, = T__Complex)
-S(_C99|_GNUC, _Imaginary, )
-S(_ALL, __real__, )
-S(_ALL, __real, = T___real__)
-S(_ALL, __imag__, )
-S(_ALL, __imag, = T___imag__)
-S(_ALL, __alignof__, )
-S(_ALL, __alignof, = T___alignof__)
-S(_MS, _alignof, = T___alignof__)
-S(_ANSI|_C99, const, )
-S(_ALL, __const, = T_const)
-S(_ALL, __const__, = T_const)
-S(_C99, restrict, )
-S(_ALL, __restrict__, = T_restrict)
-S(_ALL, __restrict, = T_restrict)
-S(_MS, _restrict, = T_restrict)
-S(_ALL, asm, )
-S(_ALL, __asm__, = T_asm)
-S(_MS, _asm, = T_asm)
-S(_ALL, __asm, = T_asm)
-S(_ANSI|_C99, volatile, )
-S(_ALL, __volatile, = T_volatile)
-S(_ALL, __volatile__, = T_volatile)
-S(_C99|_CXX, inline, )
-S(_ALL, __inline, = T_inline)
-S(_ALL, __inline__, = T_inline)
-S(_GNUC, typeof, )
-S(_ALL, __typeof, = T_typeof)
-S(_ALL, __typeof__, = T_typeof)
-S(_ALL, __attribute__, )
+S(_ANSI|_C99|_CXX, signed, )
+S(_ALL, __signed, = T_signed)
+S(_ALL, __signed__, = T_signed)
+S(_C99|_GNUC, _Complex, )
+S(_ALL, __complex__, = T__Complex)
+S(_ALL, __complex, = T__Complex)
+S(_C99|_GNUC, _Imaginary, )
+S(_ALL, __real__, )
+S(_ALL, __real, = T___real__)
+S(_ALL, __imag__, )
+S(_ALL, __imag, = T___imag__)
+S(_ALL, __alignof__, )
+S(_ALL, __alignof, = T___alignof__)
+S(_MS, _alignof, = T___alignof__)
+S(_ANSI|_C99|_CXX, const, )
+S(_ALL, __const, = T_const)
+S(_ALL, __const__, = T_const)
+S(_C99, restrict, )
+S(_ALL, __restrict__, = T_restrict)
+S(_ALL, __restrict, = T_restrict)
+S(_MS, _restrict, = T_restrict)
+S(_ALL, asm, )
+S(_ALL, __asm__, = T_asm)
+S(_MS, _asm, = T_asm)
+S(_ALL, __asm, = T_asm)
+S(_ANSI|_C99|_CXX, volatile, )
+S(_ALL, __volatile, = T_volatile)
+S(_ALL, __volatile__, = T_volatile)
+S(_C99|_CXX, inline, )
+S(_ALL, __inline, = T_inline)
+S(_ALL, __inline__, = T_inline)
+S(_GNUC, typeof, )
+S(_ALL, __typeof, = T_typeof)
+S(_ALL, __typeof__, = T_typeof)
+S(_ALL, __attribute__, )
-S(_ALL, __builtin_va_start, )
-S(_ALL, __builtin_stdarg_start, = T___builtin_va_start)
+S(_ALL, __builtin_va_start, )
+S(_ALL, __builtin_stdarg_start, = T___builtin_va_start)
-S(_MS, _near, )
-S(_MS, __near, = T__near)
-S(_MS, _far, )
-S(_MS, __far, = T__far)
-S(_MS, cdecl, )
-S(_MS, _cdecl, = T_cdecl)
-S(_MS, __cdecl, = T_cdecl)
-S(_MS, _stdcall, )
-S(_MS, __stdcall, = T__stdcall)
-S(_MS, _fastcall, )
-S(_MS, __fastcall, = T__fastcall)
-S(_MS, __thiscall, )
-S(_MS, _forceinline, )
-S(_MS, __forceinline, = T__forceinline)
-S(_MS, __unaligned, )
-S(_MS, _assume, )
-S(_MS, __assume, = T__assume)
-S(_MS, _try, )
-S(_MS, __try, = T__try)
-S(_MS, _finally, )
-S(_MS, __finally, = T__finally)
-S(_MS, _leave, )
-S(_MS, __leave, = T__leave)
-S(_MS, _except, )
-S(_MS, __except, = T__except)
-S(_MS, _declspec, )
-S(_MS, __declspec, = T__declspec)
-S(_MS, _based, )
-S(_MS, __based, = T__based)
-S(_MS, __noop, )
+S(_MS, _near, )
+S(_MS, __near, = T__near)
+S(_MS, _far, )
+S(_MS, __far, = T__far)
+S(_MS, cdecl, )
+S(_MS, _cdecl, = T_cdecl)
+S(_MS, __cdecl, = T_cdecl)
+S(_MS, _stdcall, )
+S(_MS, __stdcall, = T__stdcall)
+S(_MS, _fastcall, )
+S(_MS, __fastcall, = T__fastcall)
+S(_MS, __thiscall, )
+S(_MS, _forceinline, )
+S(_MS, __forceinline, = T__forceinline)
+S(_MS, __unaligned, )
+S(_MS, _assume, )
+S(_MS, __assume, = T__assume)
+S(_MS, _try, )
+S(_MS, __try, = T__try)
+S(_MS, _finally, )
+S(_MS, __finally, = T__finally)
+S(_MS, _leave, )
+S(_MS, __leave, = T__leave)
+S(_MS, _except, )
+S(_MS, __except, = T__except)
+S(_MS, _declspec, )
+S(_MS, __declspec, = T__declspec)
+S(_MS, _based, )
+S(_MS, __based, = T__based)
+S(_MS, __noop, )
-S(_MS, __ptr32, )
-S(_MS, __ptr64, )
-S(_MS, __sptr, )
-S(_MS, __uptr, )
-S(_MS, _w64, )
-S(_MS, __w64, = T__w64)
+S(_MS, __ptr32, )
+S(_MS, __ptr64, )
+S(_MS, __sptr, )
+S(_MS, __uptr, )
+S(_MS, _w64, )
+S(_MS, __w64, = T__w64)
-S(_MS, _int8, )
-S(_MS, __int8, = T__int8)
-S(_MS, _int16, )
-S(_MS, __int16, = T__int16)
-S(_MS, _int32, )
-S(_MS, __int32, = T__int32)
-S(_MS, _int64, )
-S(_MS, __int64, = T__int64)
-S(_MS, _int128, )
-S(_MS, __int128, = T__int128)
+S(_MS, _int8, )
+S(_MS, __int8, = T__int8)
+S(_MS, _int16, )
+S(_MS, __int16, = T__int16)
+S(_MS, _int32, )
+S(_MS, __int32, = T__int32)
+S(_MS, _int64, )
+S(_MS, __int64, = T__int64)
+S(_MS, _int128, )
+S(_MS, __int128, = T__int128)
#undef S
*/
static void print_function_type_pre(const function_type_t *type, bool top)
{
+ if (type->linkage != NULL) {
+ fputs("extern \"", out);
+ fputs(type->linkage->string, out);
+ fputs("\" ", out);
+ }
+
print_type_qualifiers(type->base.qualifiers);
if (type->base.qualifiers != 0)
fputc(' ', out);
-
intern_print_type_pre(type->return_type, false);
- switch (type->calling_convention) {
+#if 0
+ /* TODO: revive with linkage */
+ switch (type->linkage) {
case CC_CDECL:
fputs("__cdecl ", out);
break;
case CC_DEFAULT:
break;
}
+#endif
/* don't emit parenthesis if we're the toplevel type... */
if (!top)
if (!types_compatible(ret1, ret2))
return false;
- if (func1->calling_convention != func2->calling_convention)
+ if (func1->linkage != func2->linkage)
return false;
/* can parameters be compared? */
result ^= hash_ptr(parameter->type);
parameter = parameter->next;
}
- result += type->calling_convention;
+ result ^= hash_ptr(type->linkage);
return result;
}
return false;
if (type1->kr_style_parameters != type2->kr_style_parameters)
return false;
- if (type1->calling_convention != type2->calling_convention)
+ if (type1->linkage != type2->linkage)
return false;
function_parameter_t *param1 = type1->parameters;
type_base_t base;
type_t *return_type; /**< The return type. */
function_parameter_t *parameters; /**< A list of the parameter types. */
- cc_kind_t calling_convention; /**< The specified calling convention. */
+ symbol_t *linkage;
bool variadic : 1;
bool unspecified_parameters : 1;
bool kr_style_parameters : 1;
#include "lang_features.h"
#include "entity_t.h"
-atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
-
/** The error type. */
type_t *type_error_type;