/* %Z%%M% %I% %E% */ /* * Copyright (c) 1991, 1992, 1993, 1995 by Wayne C. Gramlich. * All rights reserved. * * Permission to use, copy, modify, distribute, and sell this software * for any purpose is hereby granted without fee provided that the above * copyright notice and this permission are retained. The author makes * no representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. */ /* This file contains code for convert call tress into C code: */ #ifndef CALL_DEFS_H #include "call_defs.h" #endif #ifndef ERROR_EXPORTS_H #include "error_exports.h" #endif #ifndef FLAGS_DEFS_H #include "flags_defs.h" #endif #ifndef GEN_DEFS_H #include "gen_defs.h" #endif #ifndef LINT_H #include "lint.h" #endif #ifndef OBJECT_DEFS_H #include "object_defs.h" #endif #ifndef ROUTINE_DEFS_H #include "routine_defs.h" #endif #ifndef STR_EXPORTS_H #include "str_exports.h" #endif #ifndef TYPE_DEFS_H #include "type_defs.h" #endif #ifndef UNIX_ASSERT_H #include "unix_assert.h" #endif #ifndef UNIX_CTYPE_H #include "unix_ctype.h" #endif #ifndef UNIX_UNISTD_H #include "unix_unistd.h" #endif #ifndef VECTOR_DEFS_H #include "vector_defs.h" #endif /* * call_gen(call, indent, gen) * This routine will print "call" out indented by "indent" using "gen". */ void call_gen( Call call, int indent, Gen gen) { switch (call->type) { case Call_type_and_if: { Call_binary binary; binary = call->value.binary; gen_out(gen, "("); call_gen(binary->left, 0, gen); gen_out(gen, " && "); call_gen(binary->right, 0, gen); gen_out(gen, ")"); break; } case Call_type_assign: { Call_assign assign; gen_out(gen, "%\t", indent); assign = call->value.assign; call_gen(assign->left, 0, gen); gen_out(gen, " = "); call_gen(assign->right, 0, gen); gen_out(gen, ";\n"); break; } case Call_type_cast: { Call_cast cast; Str name; cast = call->value.cast; name = cast->type_ref->name; if (type_ref_contains_parameter(cast->type_ref)) { gen_out(gen, "((void *)"); } else { gen_out(gen, "((%T)", name); } call_gen(cast->call, 0, gen); gen_out(gen, ")"); break; } case Call_type_error: gen_out(gen, "0"); break; case Call_type_if: { Call_if call_if; call_if = call->value.xif; gen_out(gen, "("); call_gen(call_if->condition, 0, gen); gen_out(gen, " ? "); call_gen(call_if->true, 0, gen); gen_out(gen, " : "); call_gen(call_if->false, 0, gen); gen_out(gen, ")"); break; } case Call_type_integer: gen_out(gen, "%d", call->value.integer); break; case Call_type_invoke: { Call actual; Vec(Call) actuals; Call_routine call_routine; Call_invoke invoke; int index; int proc_var; Routine_ref routine_ref; Str separator; int size; separator = "("; invoke = call->value.invoke; switch(invoke->call->type) { case Call_type_routine: case Call_type_var: case Call_type_temp: break; default: assert_fail(); } actuals = invoke->actuals; size = vec_size(Call, actuals); if ((gen->flags->opt_base_types) && (invoke->call->type == Call_type_routine)) { /* See whether routine is a base type: */ Str type; Str name; Str operator; int unary; call_routine = invoke->call->value.routine; routine_ref = call_routine->routine_ref; name = routine_ref->name; type = routine_ref->type_ref->name; unary = 0; operator = (Str)0; if (strequal(type, "integer") || strequal(type, "unsigned")) { if (strequal(name, "add")) { operator = "+"; } else if (strequal(name, "and")) { operator = "&"; } else if (strequal(name, "divide")) { operator = "/"; } else if (strequal(name, "equal")) { operator = "=="; } else if (strequal(name, "greater_than")) { operator = ">"; } else if (strequal(name, "left_shift")) { operator = "<<"; } else if (strequal(name, "less_than")) { operator = "<"; } else if (strequal(name, "minus")) { operator = "-"; unary = 1; } else if (strequal(name, "multiply")) { operator = "*"; } else if (strequal(name, "not")) { operator = "~"; unary = 1; } else if (strequal(name, "or")) { operator = "|"; } else if (strequal(name, "remainder")) { operator = "%"; } else if (strequal(name, "subtract")) { operator = "-"; } else if (strequal(name, "xor")) { operator = "^"; } } if (operator != (Str)0) { gen_out(gen, "("); if (unary) { assert(size == 1); actual = vec_fetch(Call, actuals, 0); gen_out(gen, "%s", operator); call_gen(actual, 0, gen); } else { assert(size == 2); actual = vec_fetch(Call, actuals, 0); call_gen(actual, 0, gen); gen_out(gen, "%s", operator); actual = vec_fetch(Call, actuals, 1); call_gen(actual, 0, gen); } gen_out(gen, ")"); break; } } gen_out(gen, "%\t", indent); proc_var = (invoke->call->type != Call_type_routine); if (proc_var) { gen_out(gen, "(*"); call_gen(invoke->call, 0, gen); gen_out(gen, "->routine)"); } else if (invoke->call->type == Call_type_routine) { Routine routine; Type_ref type_ref; call_routine = invoke->call->value.routine; routine_ref = call_routine->routine_ref; type_ref = routine_ref->type_ref; routine = gen->routine; /* Figure out whether the parameter block is needed: */ if (type_ref_contains_parameter(type_ref)) { gen_out(gen, "(*((%s__%s__block__type *)_block_)" "->%m__%s->routine)", routine->type_ref->name, routine->name, type_ref, routine_ref->name); } else if (type_ref_is_parameterized(type_ref)) { gen_out(gen, "(*%s__%s__static.%m__%s->routine)", routine->type_ref->name, routine->name, type_ref, routine_ref->name); } else if (type_ref_is_routine(type_ref) && strequal(routine_ref->name, "print")) { gen_out(gen, "run__time__routine_print"); separator = "((void *)"; } else { gen_out(gen, "%s__%s", type_ref->name, routine_ref->name); } } else { call_gen(invoke->call, 0, gen); } for (index = 0; index < size; index++) { gen_out(gen, "%s", separator); separator = ", "; actual = vec_fetch(Call, actuals, index); call_gen(actual, 0, gen); } /* Decide whether to pass in a parameter block. */ if (proc_var) { gen_out(gen, "%s", separator); call_gen(invoke->call, 0, gen); gen_out(gen, "->parameter"); separator = ","; } else if (invoke->call->type == Call_type_routine) { Routine routine; Type_ref type_ref; call_routine = invoke->call->value.routine; routine_ref = call_routine->routine_ref; type_ref = routine_ref->type_ref; routine = gen->routine; /* Figure out whether the parameter block is needed: */ if (type_ref_contains_parameter(type_ref)) { gen_out(gen, "%s((%s__%s__block__type *)_block_)" "->%m__%s->parameter", separator, routine->type_ref->name, routine->name, type_ref, routine_ref->name); separator = ","; } else if (type_ref_is_parameterized(type_ref)) { gen_out(gen, "%s%s__%s__static.%m__%s->parameter", separator, routine->type_ref->name, routine->name, type_ref, routine_ref->name); separator = ","; } } if (separator[0] == '(') { gen_out(gen, "("); } gen_out(gen, ")"); if (indent > 0) { gen_out(gen, ";\n"); } break; } case Call_type_multi: { Type_ref after_type_ref; Type_refs after_type_refs; Type_ref before_type_ref; Type_refs before_type_refs; int index; Call_multi multi; int size; Call var; Vec(Call) vars; multi = call->value.multi; vars = multi->vars; gen_out(gen, "%\t{\n", indent); indent++; after_type_refs = call->type_refs; before_type_refs = multi->type_refs; gen_out(gen, "%\t%s x__;\n", indent, type_refs_multiple_string(before_type_refs, gen->heap)); gen_out(gen, "%\tx__ = ", indent); call_gen(multi->invoke, 0, gen); gen_out(gen, ";\n"); size = vec_size(Call, vars); for (index = 0; index < size; index++) { var = vec_fetch(Call, vars, index); gen_out(gen, "%\t", indent); switch (var->type) { case Call_type_temp: { Call_temp call_temp; call_temp = var->value.temp; gen_out(gen, "t__%d", call_temp->number); break; } case Call_type_var: { Call_var call_var; call_var = var->value.var; gen_out(gen, "%s", call_var->name); break; } default: assert_fail(); } gen_out(gen, " = "); after_type_ref = type_refs_fetch(after_type_refs, index); before_type_ref = type_refs_fetch(before_type_refs, index); if (!type_ref_equal(before_type_ref, after_type_ref)) { gen_out(gen, "(%T)", after_type_ref->name); } gen_out(gen, "x__.x%d;\n", index); } indent--; gen_out(gen, "%\t}\n", indent); break; } case Call_type_not: { gen_out(gen, "!("); call_gen(call->value.not, 0, gen); gen_out(gen, ")"); break; } case Call_type_object: { int is_initial; Str name; Object_ref object_ref; Type_ref type_ref; Routine routine; object_ref = call->value.object; name = object_ref->name; is_initial = strequal(name, "??"); if (is_initial) { name = "_initial"; } type_ref = object_ref->type_ref; routine = gen->routine; if (type_ref_contains_parameter(type_ref)) { gen_out(gen, "((%s__%s__block__type *)_block_)->%m__%s", routine->type_ref->name, routine->name, type_ref, name); } else if (type_ref_is_parameterized(type_ref)) { gen_out(gen, "%s__%s__static.%m__%s", routine->type_ref->name, routine->name, type_ref, name); } else if (is_initial && type_ref_is_routine(type_ref)) { gen_out(gen, "(%T)run__time__uninitialized__routine", type_ref->name); } else { gen_out(gen, "%r__%s", type_ref, name); } break; } case Call_type_or_if: { Call_binary binary; binary = call->value.binary; gen_out(gen, "("); call_gen(binary->left, 0, gen); gen_out(gen, " || "); call_gen(binary->right, 0, gen); gen_out(gen, ")"); break; } case Call_type_routine_param: { Call_routine_param call_routine_param; Routine_ref routine_ref; call_routine_param = call->value.routine_param; routine_ref = call_routine_param->routine_ref; if (call_routine_param->parameterized) { gen_out(gen, "_parameters_->%m__%s->parameter", routine_ref->type_ref, routine_ref->name); } else { gen_out(gen, "&%m__%s__struct.parameter", routine_ref->type_ref, routine_ref->name); } break; } case Call_type_routine: { Call_routine call_routine; Routine_ref routine_ref; call_routine = call->value.routine; routine_ref = call_routine->routine_ref; gen_out(gen, "&%m__%s__struct", routine_ref->type_ref, routine_ref->name); break; } case Call_type_string: gen_out(gen, "%#", call->value.string); break; case Call_type_temp: { Call_temp call_temp; call_temp = call->value.temp; gen_out(gen, "t__%d", call_temp->number); break; } case Call_type_text: gen_out(gen, "%#", call->value.text); break; case Call_type_var: { Call_var call_var; call_var = call->value.var; gen_out(gen, "%s%S", gen->frame, call_var->name); break; } default: assert_fail(); } } /* * call_list_gen(calls, indent, gen) * This routine will print each call object in "calls" out indented * by "indent" using "gen". */ void call_list_gen( Vec(Call) calls, int indent, Gen gen) { Call call; VEC_LOOP(Call, calls, call) { call_gen(call, indent, gen); } }