Signed-off-by: Jon Loeliger <[EMAIL PROTECTED]> --- ir.c | 190 ++++++++++++++++++++++ ir_builtin.c | 180 +++++++++++++++++++++ ir_dump.c | 220 ++++++++++++++++++++++++++ ir_emit.c | 491 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ir_scope.c | 319 +++++++++++++++++++++++++++++++++++++ 5 files changed, 1400 insertions(+), 0 deletions(-) create mode 100644 ir.c create mode 100644 ir_builtin.c create mode 100644 ir_dump.c create mode 100644 ir_emit.c create mode 100644 ir_scope.c
diff --git a/ir.c b/ir.c new file mode 100644 index 0000000..7ebe806 --- /dev/null +++ b/ir.c @@ -0,0 +1,190 @@ +/* + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * 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 "dtc.h" +#include "ir.h" + +extern int treesource_error; + + +struct ir *the_ir_tree; + + +extern struct ir * +ir_alloc(ir_type ir_type, srcpos *pos) +{ + struct ir *ir; + + ir = xmalloc(sizeof(struct ir)); + memset(ir, 0, sizeof(struct ir)); + + ir->ir_type = ir_type; + ir->ir_srcpos = srcpos_copy(pos); + + return ir; +} + + +/* + * Shallow copy, mostly. + * + * Note that things like the immediate strings and source position + * are copied, but the sub-IR-expressions are not. + */ +extern struct ir * +ir_copy(struct ir *ir) +{ + struct ir *ir_new; + + if (!ir) + return NULL; + + ir_new = ir_alloc(ir->ir_type, ir->ir_srcpos); + ir_new->ir_literal = ir->ir_literal; + if (ir->ir_lit_str) + ir_new->ir_lit_str = strdup(ir->ir_lit_str); + if (ir->ir_label_name) + ir_new->ir_label_name = strdup(ir->ir_label_name); + + return ir_new; +} + + +void +ir_free(struct ir *ir) +{ +} + + +void +ir_free_all(struct ir *ir) +{ +} + + +extern struct ir * +ir_alloc_unop(ir_type ir_type, struct ir *ir1, srcpos *pos) +{ + struct ir *ir; + + ir = ir_alloc(ir_type, pos); + ir->ir_expr1 = ir1; + + return ir; +} + + +extern struct ir * +ir_alloc_binop(ir_type ir_type, + struct ir *ir1, struct ir *ir2, + srcpos *pos) +{ + struct ir *ir; + + ir = ir_alloc(ir_type, pos); + ir->ir_expr1 = ir1; + ir->ir_expr2 = ir2; + + return ir; +} + + +extern struct ir * +ir_alloc_triop(ir_type ir_type, + struct ir *ir1, struct ir *ir2, struct ir *ir3, + srcpos *pos) +{ + struct ir *ir; + + ir = ir_alloc(ir_type, pos); + ir->ir_expr1 = ir1; + ir->ir_expr2 = ir2; + ir->ir_expr3 = ir3; + + return ir; +} + + +extern struct ir * +ir_list_append(struct ir *ir_list, struct ir *ir_node) +{ + if (ir_node == NULL) { + return ir_list; + } + + if (ir_list == NULL) { + ir_list = ir_alloc(IR_LIST, ir_node->ir_srcpos); + } + + ir_node->ir_prev = ir_list->ir_last; + + if (ir_list->ir_last) { + ir_list->ir_last->ir_next = ir_node; + } else { + ir_list->ir_first = ir_node; + } + + ir_list->ir_last = ir_node; + + return ir_list; +} + + +void +ir_process(void) +{ + /* + * FIXME: Fix leaking the whole orginal IR tree here. + */ + the_ir_tree = ir_simplify(the_ir_tree, IR_EVAL_CTXT_ANY); + + ir_emit(the_ir_tree); +} + + +static const char *ir_severity_str[] = { + "Info", + "Warning", + "Error", +}; + +#define IR_NUM_SEV ARRAY_SIZE(ir_severity_str) + + +void +ir_msg(ir_severity_t severity, struct ir *ir, char const *fmt, ...) +{ + srcpos *pos; + const char *srcstr; + va_list va; + va_start(va, fmt); + + pos = ir ? ir->ir_srcpos : &srcpos_empty; + srcstr = srcpos_string(pos); + + if (severity >= IR_NUM_SEV) + severity = IR_SEV_INFO; + + fprintf(stderr, "%s: %s ", ir_severity_str[severity], srcstr); + + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); + + va_end(va); +} diff --git a/ir_builtin.c b/ir_builtin.c new file mode 100644 index 0000000..c448502 --- /dev/null +++ b/ir_builtin.c @@ -0,0 +1,180 @@ +/* + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * 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 <stdio.h> + +#include "dtc.h" +#include "ir.h" + + +typedef struct ir * (*irb_impl_func)(struct ir *ir_params); + +struct builtin_func { + char *name; + irb_impl_func implementation; +}; + +struct ir *ir_builtin_join(struct ir *ir_params); +struct ir *ir_builtin_hexstr(struct ir *ir_params); + +static const struct builtin_func builtin_table[] = { + { "join", ir_builtin_join }, + { "hexstr", ir_builtin_hexstr }, +}; + +#define IRB_NUM_BUILTINS ARRAY_SIZE(builtin_table) + + +irb_id +ir_lookup_builtin_by_name(char *str_name) +{ + irb_id irb; + + for (irb = 0; irb < IRB_NUM_BUILTINS; irb++) { + if (strcmp(builtin_table[irb].name, str_name) == 0) { + return irb; + } + } + + return IRB_UNDEF; +} + + +struct ir * +ir_eval_builtin(struct ir *ir) +{ + irb_id irb; + const struct builtin_func *bf; + + if (ir == NULL) + return NULL; + + if (ir->ir_type != IR_BUILTIN) + return NULL; + + irb = ir->ir_builtin_id; + + if (irb <= IRB_UNDEF || irb >= IRB_NUM_BUILTINS) + return NULL; + + bf = &builtin_table[irb]; + + return (*bf->implementation)(ir); +} + + +struct ir * +ir_builtin_join(struct ir *ir_builtin) +{ + struct ir *ir_new; + struct ir *irp; + struct ir *ir; + char *s; + char *str; + int len; + char buf[30]; + + debug("ir_builtin_impl_join():\n"); + + irp = ir_builtin->ir_expr1; + if (irp->ir_type == IR_LIST) + irp = irp->ir_first; + + len = 1; + str = xmalloc(1); + *str = 0; + + while (irp != NULL) { + ir = ir_eval(irp); + + if (ir_is_string(ir)) { + s = ir_eval_for_c_string(ir); + } else if (ir_is_constant(ir)) { + unsigned long long a; + a = ir_eval_for_addr(ir); + snprintf(buf, sizeof(buf), "%llu", a); + s = buf; + } else { + ir_error(ir, + "Can't handle %s in join()\n", + ir_type_string(ir->ir_type)); + s = 0; + } + + len += strlen(s); + + str = xrealloc(str, len); + strcat(str, s); + + irp = irp->ir_next; + } + + ir_new = ir_alloc(IR_LIT_STR, ir_builtin->ir_srcpos); + ir_new->ir_lit_str = str; + + return ir_new; +} + + + +struct ir * +ir_builtin_hexstr(struct ir *ir_builtin) +{ + struct ir *ir_new; + struct ir *irp; + struct ir *ir; + char *s; + char *str; + int len; + char buf[30]; + + irp = ir_builtin->ir_expr1; + if (irp->ir_type == IR_LIST) + irp = irp->ir_first; + + len = 1; + str = xmalloc(1); + *str = 0; + + while (irp != NULL) { + ir = ir_eval(irp); + if (ir_is_constant(ir)) { + unsigned long long a; + a = ir_eval_for_addr(ir); + snprintf(buf, 30, "%llx", a); + s = buf; + } else { + ir_error(ir, + "Can't handle %s in hexstr()\n", + ir_type_string(ir->ir_type)); + s = 0; + } + len += strlen(s); + + str = xrealloc(str, len); + strcat(str, s); + + irp = irp->ir_next; + } + + ir_new = ir_alloc(IR_LIT_STR, ir_builtin->ir_srcpos); + ir_new->ir_lit_str = str; + + return ir_new; +} diff --git a/ir_dump.c b/ir_dump.c new file mode 100644 index 0000000..f949423 --- /dev/null +++ b/ir_dump.c @@ -0,0 +1,220 @@ +/* + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * 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 <stdio.h> + +#include "dtc.h" +#include "ir.h" + + +static const char *ir_type_str[IR_NUM_TYPES] = { + "IR_UNDEF", + "IR_ROOT", + "IR_MEM_RESERVE", + "IR_ASSIGN", + "IR_PROP_DEF", + "IR_REF_PHANDLE", + "IR_REF_PATH", + "IR_CELL", + "IR_LITERAL", + "IR_LIT_STR", + "IR_LIT_BYTE", + "IR_LABEL", + "IR_LIST", + "IR_INCBIN", + "IR_BUILTIN", + "IR_SELECT", + "IR_OR", + "IR_AND", + "IR_BIT_OR", + "IR_BIT_XOR", + "IR_BIT_AND", + "IR_EQ", + "IR_LT", + "IR_LE", + "IR_GT", + "IR_GE", + "IR_NE", + "IR_LSHIFT", + "IR_RSHIFT", + "IR_ADD", + "IR_MINUS", + "IR_MULT", + "IR_DIV", + "IR_MOD", + "IR_UMINUS", + "IR_BIT_COMPL", + "IR_NOT", + "IR_FUNC_DEF", + "IR_FOR", + "IR_RETURN", + "IR_RANGE", + "IR_ID", + "IR_IF", + "IR_PARAMDECL", + "IR_FUNC_CALL", + "IR_NODE", + "IR_PROPNODENAME", + "IR_LIT_CELL", + "IR_LIT_ADDR", + "IR_CVT_PROPNODENAME", + "IR_CVT_STRING", + "IR_CONST_DEF", +}; + + +const char * +ir_type_string(ir_type ir_type) +{ + if (0 <= ir_type && ir_type < IR_NUM_TYPES) + return ir_type_str[ir_type]; + else + return "<unknown>"; +} + + +static void +ir_dump_node(struct ir *ir, unsigned int level) +{ + int indent = 4 * level; + struct ir *iri; + + if (ir == NULL) + return; + + /* + * Print node values + */ + printf("%*sNODE : %p\n", + indent, "", ir); + + printf("%*sir_type : %s\n", + indent, "", ir_type_string(ir->ir_type)); + + printf("%*sir_srcpos : %s\n", + indent, "", srcpos_string(ir->ir_srcpos)); + + + printf("%*sir_literal : %lld\n", indent, "", ir->ir_literal); + + if (ir->ir_builtin_id != IRB_UNDEF) { + printf("%*sir_builtin_id : %d\n", + indent, "", ir->ir_builtin_id); + } + if (ir->ir_lit_str) { + printf("%*sir_lit_str : %s\n", + indent, "", ir->ir_lit_str); + } + if (ir->ir_label_name) { + printf("%*sir_label_name : %s\n", + indent, "", ir->ir_label_name); + } + + if (ir->ir_name) { + printf("%*sir_name : %p\n", + indent, "", ir->ir_name); + ir_dump_node(ir->ir_name, level + 1); + } + + if (ir->ir_label) { + printf("%*sir_label : %p\n", + indent, "", ir->ir_label); + ir_dump_node(ir->ir_label, level + 1); + } + + if (ir->ir_first) + printf("%*sir_first : %p\n", + indent, "", ir->ir_first); + if (ir->ir_last) + printf("%*sir_last : %p\n", + indent, "", ir->ir_last); + if (ir->ir_next) + printf("%*sir_next : %p\n", + indent, "", ir->ir_next); + if (ir->ir_prev) + printf("%*sir_prev : %p\n", + indent, "", ir->ir_prev); + + /* + * Dump mem-reserves. + */ + if (ir->ir_mem_reserves) { + printf("%*sir_mem_reserves: %p\n", + indent, "", ir->ir_mem_reserves); + ir_dump_node(ir->ir_mem_reserves, level + 1); + } + + /* + * Dump sub-expressions + */ + if (ir->ir_expr1) { + printf("%*sir_expr1 : %p\n", + indent, "", ir->ir_expr1); + ir_dump_node(ir->ir_expr1, level + 1); + } + + if (ir->ir_expr2) { + printf("%*sir_expr2 : %p\n", + indent, "", ir->ir_expr2); + ir_dump_node(ir->ir_expr2, level + 1); + } + + if (ir->ir_expr3) { + printf("%*sir_expr3 : %p\n", + indent, "", ir->ir_expr3); + ir_dump_node(ir->ir_expr3, level + 1); + } + + /* + * Recursively dump declarations. + */ + if (ir->ir_declarations) { + printf("%*sir_declarations: %p\n", + indent, "", ir->ir_declarations); + ir_dump_node(ir->ir_declarations, level + 1); + } + + /* + * Recursively dump statements. + */ + if (ir->ir_statements) { + printf("%*sir_statements: %p\n", + indent, "", ir->ir_statements); + ir_dump_node(ir->ir_statements, level + 1); + } + if (ir->ir_statements2) { + printf("%*sir_statements2: %p\n", + indent, "", ir->ir_statements2); + ir_dump_node(ir->ir_statements2, level + 1); + } + + /* + * Recursively dump LIST chain. + */ + for (iri = ir->ir_first; iri != NULL; iri = iri->ir_next) { + ir_dump_node(iri, level + 1); + } +} + + +extern void +ir_dump(struct ir *ir) +{ + ir_dump_node(ir, 0); +} diff --git a/ir_emit.c b/ir_emit.c new file mode 100644 index 0000000..31005ca --- /dev/null +++ b/ir_emit.c @@ -0,0 +1,491 @@ +/* + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * 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 <stdio.h> + +#include "dtc.h" +#include "ir.h" +#include "ir_scope.h" +#include "nv.h" + +extern struct boot_info *the_boot_info; + + +void ir_emit_node(struct ir *ir); + + +void +ir_emit_prop_def(struct ir *irp) +{ + struct ir *ir_lhs; + struct property *p; + char *prop_name; + char *lab; + struct data d; + + debug("ir_emit_prop_def("); + + lab = ir_eval_for_label(irp->ir_label); + if (lab) { + debug("%s : ", lab); + } + + ir_lhs = ir_eval(irp->ir_expr1); + prop_name = ir_eval_for_name(ir_lhs); + debug("%s = <expr>)\n", prop_name); + + if (prop_name) { + d = empty_data; + ir_eval_for_data(irp->ir_expr2, &d); + p = build_property(prop_name, d, lab); + irs_append_property(p); + } + + debug("ir_emit_prop_def(): Done\n"); +} + + +void +ir_emit_assign(struct ir *ir_assign) +{ + char *var_name; + struct ir_symbol *irsym; + struct ir *ir_val; + struct ir *ir_pos; + + ir_pos = ir_assign->ir_expr1 ? ir_assign->ir_expr1 : ir_assign; + + var_name = ir_eval_for_name(ir_assign->ir_expr1); + + debug("ir_emit_assign(%s)\n", var_name); + + if (!var_name) { + ir_error(ir_pos, "Can't determine LHS name\n"); + return; + } + + irsym = irs_lookup_local(var_name); + if (irsym != NULL) { + if (irsym->irsym_type == IRSYM_CONST) { + ir_error(ir_pos, + "Can't assign to constant \"%s\"\n", + var_name); + } + } else { + /* + * FIXME: Debate on-the-fly creation or pre-declaration. + */ + irsym = irs_create_local(var_name, IRSYM_VAR); + } + + ir_val = ir_eval(ir_assign->ir_expr2); + irsym->irsym_value = ir_val; +} + + +void +ir_emit_for(struct ir *ir_for) +{ + char *var_name; + struct ir_symbol *irsym; + struct ir *ir_id; + struct ir *ir_val; + struct ir *ir_range; + unsigned long long var; + unsigned long long start; + unsigned long long stop; + + irs_push_scope(IRS_FOR_LOOP); + + /* + * Introduce for-loop variable into FOR_LOOP scope. + */ + ir_id = ir_for->ir_expr1; + var_name = ir_eval_for_name(ir_id); + irsym = irs_create_local(var_name, IRSYM_VAR); + + ir_val = ir_alloc(IR_LIT_ADDR, ir_id->ir_srcpos); + irsym->irsym_value = ir_val; + + ir_range = ir_for->ir_expr2; + start = ir_eval_for_addr(ir_range->ir_expr1); + stop = ir_eval_for_addr(ir_range->ir_expr2); + + debug("Range appears to be %llu to %llu\n", start, stop); + + var = start; + while (var <= stop ) { + ir_val->ir_literal = var; + ir_emit_statement_list(ir_for->ir_statements); + var++; + } + + irs_pop_scope(); +} + + +void +ir_emit_if(struct ir *ir_if) +{ + uint64_t lit; + + debug("ir_if()\n"); + lit = ir_eval_for_addr(ir_if->ir_expr1); + if (lit) { + ir_emit_statement_list(ir_if->ir_statements); + } else { + ir_emit_statement_list(ir_if->ir_statements2); + } +} + + +void +ir_emit_return(struct ir *ir_return) +{ + struct ir *ir_ret_expr; + + ir_ret_expr = ir_eval(ir_return->ir_expr1); + irs_set_return_value(ir_ret_expr); +} + + +void +ir_emit_func_call(struct ir *ir_func) +{ + struct ir_scope *irs_scope; + + /* + * Perform function body. + * + * Returned scope has node and property "side effects". + * Function return value is thrown to /dev/null. + */ + irs_scope = ir_eval_func_body(ir_func); + + /* + * Propagate any nodes or properties into parent scope. + */ + irs_scope_append_property_list(irs_scope->irs_prop_list); + irs_scope_append_node_list(irs_scope->irs_node_list); +} + + +void +ir_emit_statement(struct ir *ir) +{ + if (ir == NULL) + return; + + switch (ir->ir_type) { + case IR_NODE: + ir_emit_node(ir); + break; + + case IR_PROP_DEF: + ir_emit_prop_def(ir); + break; + + case IR_FOR: + ir_emit_for(ir); + break; + + case IR_IF: + ir_emit_if(ir); + break; + + case IR_RETURN: + ir_emit_return(ir); + break; + + case IR_ASSIGN: + ir_emit_assign(ir); + break; + + case IR_FUNC_CALL: + ir_emit_func_call(ir); + break; + + case IR_LIST: + /* + * FIXME: LIST within a LIST. Optimize out earlier? + */ + ir_emit_statement_list(ir); + break; + + default: + ir_error(ir, "Unknown statement with ir_type %s\n", + ir_type_string(ir->ir_type)); + } +} + + +void +ir_emit_statement_list(struct ir *ir_list) +{ + struct ir *ir; + + if (ir_list == NULL) + return; + + if (ir_list->ir_type != IR_LIST) + return; + + for (ir = ir_list->ir_first; ir != NULL; ir = ir->ir_next) { + ir_emit_statement(ir); + } +} + + +/* + * Enter a /define/ function definitin into IRS_ROOT symtab. + */ +void +ir_emit_func_def(struct ir *ir_func_def) +{ + char *func_name; + struct ir_symbol *irsym; + struct ir *ir_pos; + + ir_pos = ir_func_def->ir_expr1 + ? ir_func_def->ir_expr1 : ir_func_def; + + func_name = ir_eval_for_name(ir_func_def->ir_name); + + + irsym = irs_lookup(func_name, IRS_ROOT); + if (irsym != NULL) { + ir_error(ir_pos, + "Redefinintion of \"%s\" ignored\n", + func_name); + return; + } + + irsym = irs_create_symbol(IRS_ROOT, func_name, IRSYM_FUNCDEF); + + irsym->irsym_value = ir_func_def; + + debug("ir_emit_func_def(): Defined %s\n", func_name); +} + + +/* + * Enter a /define/ function definitin into IRS_ROOT symtab. + */ +void +ir_emit_const_def(struct ir *ir_const_def) +{ + char *const_name; + struct ir_symbol *irsym; + struct ir *ir_val; + struct ir *ir_pos; + + ir_pos = ir_const_def->ir_expr1 + ? ir_const_def->ir_expr1 : ir_const_def; + + const_name = ir_eval_for_name(ir_const_def->ir_expr1); + + debug("ir_const_def(%s)\n", const_name); + + if (!const_name) { + ir_error(ir_pos, "Can't determine LHS constant name\n"); + return; + } + + irsym = irs_lookup(const_name, IRS_ANY); + if (irsym != NULL) { + ir_warn(ir_pos, + "Redefinintion of \"%s\" ignored\n", + const_name); + return; + } + + irsym = irs_create_symbol(IRS_ROOT, const_name, IRSYM_CONST); + + ir_val = ir_eval(ir_const_def->ir_expr2); + irsym->irsym_value = ir_val; +} + + +void +ir_emit_declaration_list(struct ir *ir_list) +{ + struct ir *ir; + + if (ir_list == NULL) + return; + + if (ir_list->ir_type != IR_LIST) + return; + + for (ir = ir_list->ir_first; ir != NULL; ir = ir->ir_next) { + switch (ir->ir_type) { + case IR_CONST_DEF: + ir_emit_const_def(ir); + break; + + case IR_FUNC_DEF: + ir_emit_func_def(ir); + break; + + default: + ir_error(ir, + "Unknown devlaration type %s\n", + ir_type_string(ir->ir_type)); + break; + } + } +} + + +void +ir_emit_node(struct ir *ir) +{ + struct ir *ir_name; + struct ir *ir_label; + char *name; + char *label; + struct node *node; + struct node *node_list; + struct ir_scope *irs_scope; + + if (ir == NULL) + return; + + if (ir->ir_type != IR_NODE) + return; + + ir_name = ir_eval(ir->ir_name); + name = ir_eval_for_name(ir_name); + + ir_label = ir_eval(ir->ir_label); + label = ir_eval_for_label(ir_label); + + debug("ir_emit_node(): Making node %s : %s\n", label, name); + + irs_push_scope(IRS_NODE); + ir_emit_statement_list(ir->ir_statements); + irs_scope = irs_pop_scope(); + + node_list = reverse_nodes(irs_scope->irs_node_list); + node = build_node(irs_scope->irs_prop_list, node_list); + name_node(node, name, label); + + irs_append_node(node); +} + + +void +ir_emit_mem_reserves(struct ir *ir_mem) +{ + struct ir *ir; + struct reserve_info *ri; + uint64_t addr; + uint64_t size; + char *lab; + + if (ir_mem == NULL) + return; + + for (ir = ir_mem->ir_first; ir != NULL; ir = ir->ir_next) { + addr = ir_eval_for_addr(ir->ir_expr1); + size = ir_eval_for_addr(ir->ir_expr2); + lab = ir_eval_for_label(ir->ir_label); + + debug("emit: build_reserve_entry(0x%llx, 0x%llx, ", + (unsigned long long)addr, (unsigned long long)size); + if (lab) { + debug("%s)\n", lab); + } else { + debug("<no-label>)\n"); + } + + ri = build_reserve_entry(addr, size, lab); + irs_append_reserve(ri); + } +} + + +void +ir_add_cmd_line_constant_defs(void) +{ + struct nv_pair *nv; + struct ir_symbol *irsym; + struct ir *ir_const; + + for (nv = nv_list; nv != NULL; nv = nv->nv_next) { + irsym = irs_create_symbol(IRS_ROOT, nv->nv_name, IRSYM_CONST); + if (nv->nv_value) { + ir_const = ir_alloc(IR_LITERAL, &srcpos_empty); + ir_const->ir_lit_str = strdup(nv->nv_value); + irsym->irsym_value = ir_const; + } + } +} + + +void +ir_emit_root(struct ir *ir) +{ + struct reserve_info *ri_list; + struct node *node_list; + + if (ir == NULL) + return; + + if (ir->ir_type != IR_ROOT) { + ir_error(ir, "Bad root node\n"); + return; + } + + irs_push_scope(IRS_ROOT); + + /* + * Establish constant definitions from command line. + */ + ir_add_cmd_line_constant_defs(); + + ir_emit_mem_reserves(ir->ir_mem_reserves); + + /* + * Fast-and-loose... These are definitions, not declarations! + */ + ir_emit_declaration_list(ir->ir_declarations); + + /* + * Emit the root IR_NODE. + */ + ir_emit_node(ir->ir_statements); + + /* + * Build the_boot_info. + */ + ri_list = irs_scope_stack->irs_reserve_list; + node_list = irs_scope_stack->irs_node_list; + the_boot_info = build_boot_info(ri_list, node_list, 0); + + irs_pop_scope(); +} + + +extern void +ir_emit(struct ir *ir) +{ + ir_emit_root(ir); + fflush(stdout); +} diff --git a/ir_scope.c b/ir_scope.c new file mode 100644 index 0000000..c9a52e8 --- /dev/null +++ b/ir_scope.c @@ -0,0 +1,319 @@ +/* + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * 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 <stdio.h> + +#include "dtc.h" +#include "srcpos.h" +#include "ir.h" +#include "ir_scope.h" + + +struct ir_scope *irs_scope_stack; + +static const char *irs_scope_bits_str[] = { + "ROOT", + "NODE", + "FOR_LOOP", + "FUNC_CALL", +}; + + +static const char *irsym_type_str[IRSYM_NUM_TYPES] = { + "NONE", + "VAR", + "FUNCDEF", + "PARAM", + "CONST", +}; + + +void +irs_push_scope(irs_type irs_type) +{ + struct ir_scope *irs_new; + + irs_new = xmalloc(sizeof(struct ir_scope)); + memset(irs_new, 0, sizeof(struct ir_scope)); + + irs_new->irs_type = irs_type; + irs_new->irs_next = irs_scope_stack; + + irs_scope_stack = irs_new; +} + + +struct ir_scope * +irs_pop_scope() +{ + struct ir_scope *irs_top = irs_scope_stack; + + irs_scope_stack = irs_top->irs_next; + irs_top->irs_next = NULL; + + return irs_top; +} + + +void +irs_free_scope(struct ir_scope *irs) +{ + free(irs); +} + + +struct ir_scope * +irs_find_scope(irs_type irs_match) +{ + struct ir_scope *irs; + + for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) { + if (irs->irs_type & irs_match) + return irs; + } + return NULL; +} + + +void +irs_append_reserve(struct reserve_info *ri) +{ + struct ir_scope *irs; + + irs = irs_find_scope(IRS_ROOT); + irs->irs_reserve_list = chain_reserve_entry(ri, + irs->irs_reserve_list); +} + + +void +irs_scope_append_property_list(struct property *pl) +{ + struct ir_scope *irs; + struct property *p; + + irs = irs_find_scope(IRS_NODE); + for (p = pl; p != NULL; p = p->next) { + irs->irs_prop_list = chain_property(p, irs->irs_prop_list); + } +} + +void +irs_scope_append_node_list(struct node *nl) +{ + struct ir_scope *irs; + struct node *n; + + irs = irs_find_scope(IRS_NODE); + for (n = nl; n != NULL; n = n->parent) { + irs->irs_node_list = chain_node(n, irs->irs_node_list); + } +} + + +void +irs_append_property(struct property *p) +{ + struct ir_scope *irs; + + irs = irs_find_scope(IRS_NODE); + irs->irs_prop_list = chain_property(p, irs->irs_prop_list); +} + + +void +irs_append_node(struct node *n) +{ + struct ir_scope *irs; + + irs = irs_find_scope(IRS_NODE | IRS_ROOT); + irs->irs_node_list = chain_node(n, irs->irs_node_list); +} + + +void +irs_set_return_value(struct ir *ir_ret) +{ + struct ir_scope *irs; + + /* + * FIXME: If a previous irs_expr existed, it just leaked. + */ + irs = irs_find_scope(IRS_FUNC_CALL); + irs->irs_expr = ir_ret; +} + + + +struct ir_symbol * +irs_alloc_symbol(char *name, irsym_type irsym_type) +{ + struct ir_symbol *irsym; + + irsym = xmalloc(sizeof(struct ir_symbol)); + memset(irsym, 0, sizeof(struct ir_symbol)); + + irsym->irsym_type = irsym_type; + irsym->irsym_name = strdup(name); + + return irsym; +} + + +void +irs_add_symbol(struct ir_scope *irs, struct ir_symbol *irsym) +{ + irsym->irsym_next = irs->irs_symtab; + irs->irs_symtab = irsym; +} + + +struct ir_symbol * +irs_lookup_in_scope(struct ir_scope *irs, char *name) +{ + struct ir_symbol *irsym; + + for (irsym = irs->irs_symtab; irsym; irsym = irsym->irsym_next) + if (strcmp(irsym->irsym_name, name) == 0) + return irsym; + + return NULL; +} + + +struct ir_symbol * +irs_lookup(char *name, irs_type irs_type) +{ + struct ir_scope *irs; + struct ir_symbol *irsym; + + /* + * Look through scope stack finding matching scopes. + */ + for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) + if (irs->irs_type & irs_type) { + irsym = irs_lookup_in_scope(irs, name); + if (irsym != NULL) + return irsym; + } + + return NULL; +} + + +/* + * Try to find a symbol that is local to the innermost function. + * + * Look through scope stack finding matching scopes. + * Peer into FUNC_CALL, FOR_LOOP and IR_ROOT symbol tables, + * but bail at first FUNC_CALL to make them be "local". + */ +struct ir_symbol * +irs_lookup_local(char *name) +{ + struct ir_scope *irs; + struct ir_symbol *irsym; + + for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) { + if (irs->irs_type & (IRS_FUNC_CALL|IRS_FOR_LOOP|IRS_ROOT)) { + irsym = irs_lookup_in_scope(irs, name); + if (irsym != NULL) + return irsym; + if (irs->irs_type & IRS_FUNC_CALL) + return NULL; + } + } + + return NULL; +} + + +struct ir_symbol * +irs_create_local(char *name, irsym_type irsym_type) +{ + struct ir_scope *irs; + struct ir_symbol *irsym; + + for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) { + if (irs->irs_type & (IRS_FUNC_CALL|IRS_ROOT)) { + break; + } + } + + irsym = irs_alloc_symbol(name, irsym_type); + irs_add_symbol(irs_scope_stack, irsym); + + return irsym; +} + + +struct ir_symbol * +irs_create_symbol(irs_type irs_type, char *name, irsym_type irsym_type) +{ + struct ir_scope *irs; + struct ir_symbol *irsym; + + /* + * Check for prior existence of symbol first. + */ + irsym = irs_lookup(name, irs_type); + if (irsym != NULL) + return irsym; + + /* + * Create the symbol. + */ + irsym = irs_alloc_symbol(name, irsym_type); + + /* + * Locate the right scope and add symbol. + */ + irs = irs_find_scope(irs_type); + irs_add_symbol(irs, irsym); + + return irsym; +} + + +void +irs_dump_symbols(void) +{ + struct ir_scope *irs; + struct ir_symbol *irsym; + int i; + + /* + * Look through scope stack. + */ + for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) { + printf("Type: 0x%02x : ", irs->irs_type); + for (i = 0; i < IRS_MAX_BIT; i++) { + if (irs->irs_type & (1 << i)) + printf("%s ", irs_scope_bits_str[i]); + } + printf("\n"); + for (irsym = irs->irs_symtab; + irsym != NULL; + irsym = irsym->irsym_next) { + printf(" %s : %s\n", + irsym_type_str[irsym->irsym_type], + irsym->irsym_name); + } + } +} -- 1.6.0.90.g436ed _______________________________________________ devicetree-discuss mailing list devicetree-discuss@ozlabs.org https://ozlabs.org/mailman/listinfo/devicetree-discuss