1 // go-gcc.cc -- Go frontend to gcc IR.
2 // Copyright (C) 2011 Free Software Foundation, Inc.
3 // Contributed by Ian Lance Taylor, Google.
5 // This file is part of GCC.
7 // GCC is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3, or (at your option) any later
12 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 // You should have received a copy of the GNU General Public License
18 // along with GCC; see the file COPYING3. If not see
19 // <http://www.gnu.org/licenses/>.
21 #include "go-system.h"
23 // This has to be included outside of extern "C", so we have to
24 // include it here before tree.h includes it later.
27 #ifndef ENABLE_BUILD_WITH_CXX
33 #include "tree-iterator.h"
36 #ifndef ENABLE_BUILD_WITH_CXX
45 // A class wrapping a tree.
62 // In gcc, types, expressions, and statements are all trees.
63 class Btype : public Gcc_tree
71 class Bexpression : public Gcc_tree
79 class Bstatement : public Gcc_tree
87 class Bfunction : public Gcc_tree
95 class Bblock : public Gcc_tree
103 class Bvariable : public Gcc_tree
111 class Blabel : public Gcc_tree
119 // This file implements the interface between the Go frontend proper
120 // and the gcc IR. This implements specific instantiations of
121 // abstract classes defined by the Go frontend proper. The Go
122 // frontend proper class methods of these classes to generate the
123 // backend representation.
125 class Gcc_backend : public Backend
132 { gcc_unreachable(); }
136 { gcc_unreachable(); }
140 { gcc_unreachable(); }
143 integer_type(bool /* is_unsigned */, int /* bits */)
144 { gcc_unreachable(); }
147 float_type(int /* bits */)
148 { gcc_unreachable(); }
152 { gcc_unreachable(); }
155 function_type(const Function_type*, Btype* /* receiver */,
156 const Btypes* /* parameters */,
157 const Btypes* /* results */)
158 { gcc_unreachable(); }
161 struct_type(const Struct_type*, const Btypes* /* field_types */)
162 { gcc_unreachable(); }
165 array_type(const Btype* /* element_type */, const Bexpression* /* length */)
166 { gcc_unreachable(); }
169 slice_type(const Btype* /* element_type */)
170 { gcc_unreachable(); }
173 map_type(const Btype* /* key_type */, const Btype* /* value_type */,
175 { gcc_unreachable(); }
178 channel_type(const Btype* /* element_type */)
179 { gcc_unreachable(); }
182 interface_type(const Interface_type*, const Btypes* /* method_types */)
183 { gcc_unreachable(); }
189 { return this->make_statement(error_mark_node); }
192 expression_statement(Bexpression*);
195 init_statement(Bvariable* var, Bexpression* init);
198 assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location);
201 return_statement(Bfunction*, const std::vector<Bexpression*>&,
205 if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
209 switch_statement(Bexpression* value,
210 const std::vector<std::vector<Bexpression*> >& cases,
211 const std::vector<Bstatement*>& statements,
215 compound_statement(Bstatement*, Bstatement*);
218 statement_list(const std::vector<Bstatement*>&);
223 block(Bfunction*, Bblock*, const std::vector<Bvariable*>&,
224 source_location, source_location);
227 block_add_statements(Bblock*, const std::vector<Bstatement*>&);
230 block_statement(Bblock*);
236 { return new Bvariable(error_mark_node); }
239 global_variable(const std::string& package_name,
240 const std::string& unique_prefix,
241 const std::string& name,
245 source_location location);
248 global_variable_set_init(Bvariable*, Bexpression*);
251 local_variable(Bfunction*, const std::string& name, Btype* type,
255 parameter_variable(Bfunction*, const std::string& name, Btype* type,
261 label(Bfunction*, const std::string& name, source_location);
264 label_definition_statement(Blabel*);
267 goto_statement(Blabel*, source_location);
270 label_address(Blabel*, source_location);
273 // Make a Bexpression from a tree.
275 make_expression(tree t)
276 { return new Bexpression(t); }
278 // Make a Bstatement from a tree.
280 make_statement(tree t)
281 { return new Bstatement(t); }
284 // A helper function.
287 get_identifier_from_string(const std::string& str)
289 return get_identifier_with_length(str.data(), str.length());
292 // An expression as a statement.
295 Gcc_backend::expression_statement(Bexpression* expr)
297 return this->make_statement(expr->get_tree());
300 // Variable initialization.
303 Gcc_backend::init_statement(Bvariable* var, Bexpression* init)
305 tree var_tree = var->get_tree();
306 tree init_tree = init->get_tree();
307 if (var_tree == error_mark_node || init_tree == error_mark_node)
308 return this->error_statement();
309 gcc_assert(TREE_CODE(var_tree) == VAR_DECL);
310 DECL_INITIAL(var_tree) = init_tree;
311 return this->make_statement(build1_loc(DECL_SOURCE_LOCATION(var_tree),
312 DECL_EXPR, void_type_node, var_tree));
318 Gcc_backend::assignment_statement(Bexpression* lhs, Bexpression* rhs,
319 source_location location)
321 tree lhs_tree = lhs->get_tree();
322 tree rhs_tree = rhs->get_tree();
323 if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
324 return this->error_statement();
325 return this->make_statement(fold_build2_loc(location, MODIFY_EXPR,
327 lhs_tree, rhs_tree));
333 Gcc_backend::return_statement(Bfunction* bfunction,
334 const std::vector<Bexpression*>& vals,
335 source_location location)
337 tree fntree = bfunction->get_tree();
338 if (fntree == error_mark_node)
339 return this->error_statement();
340 tree result = DECL_RESULT(fntree);
341 if (result == error_mark_node)
342 return this->error_statement();
345 ret = fold_build1_loc(location, RETURN_EXPR, void_type_node, NULL_TREE);
346 else if (vals.size() == 1)
348 tree val = vals.front()->get_tree();
349 if (val == error_mark_node)
350 return this->error_statement();
351 tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
352 result, vals.front()->get_tree());
353 ret = fold_build1_loc(location, RETURN_EXPR, void_type_node, set);
357 // To return multiple values, copy the values into a temporary
358 // variable of the right structure type, and then assign the
359 // temporary variable to the DECL_RESULT in the return
361 tree stmt_list = NULL_TREE;
362 tree rettype = TREE_TYPE(result);
363 tree rettmp = create_tmp_var(rettype, "RESULT");
364 tree field = TYPE_FIELDS(rettype);
365 for (std::vector<Bexpression*>::const_iterator p = vals.begin();
367 p++, field = DECL_CHAIN(field))
369 gcc_assert(field != NULL_TREE);
370 tree ref = fold_build3_loc(location, COMPONENT_REF, TREE_TYPE(field),
371 rettmp, field, NULL_TREE);
372 tree val = (*p)->get_tree();
373 if (val == error_mark_node)
374 return this->error_statement();
375 tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
376 ref, (*p)->get_tree());
377 append_to_statement_list(set, &stmt_list);
379 gcc_assert(field == NULL_TREE);
380 tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
382 tree ret_expr = fold_build1_loc(location, RETURN_EXPR, void_type_node,
384 append_to_statement_list(ret_expr, &stmt_list);
387 return this->make_statement(ret);
393 Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
394 Bblock* else_block, source_location location)
396 tree cond_tree = condition->get_tree();
397 tree then_tree = then_block->get_tree();
398 tree else_tree = else_block == NULL ? NULL_TREE : else_block->get_tree();
399 if (cond_tree == error_mark_node
400 || then_tree == error_mark_node
401 || else_tree == error_mark_node)
402 return this->error_statement();
403 tree ret = build3_loc(location, COND_EXPR, void_type_node, cond_tree,
404 then_tree, else_tree);
405 return this->make_statement(ret);
411 Gcc_backend::switch_statement(
413 const std::vector<std::vector<Bexpression*> >& cases,
414 const std::vector<Bstatement*>& statements,
415 source_location switch_location)
417 gcc_assert(cases.size() == statements.size());
419 tree stmt_list = NULL_TREE;
420 std::vector<std::vector<Bexpression*> >::const_iterator pc = cases.begin();
421 for (std::vector<Bstatement*>::const_iterator ps = statements.begin();
422 ps != statements.end();
427 source_location loc = (*ps != NULL
428 ? EXPR_LOCATION((*ps)->get_tree())
430 tree label = create_artificial_label(loc);
431 tree c = build3_loc(loc, CASE_LABEL_EXPR, void_type_node, NULL_TREE,
433 append_to_statement_list(c, &stmt_list);
437 for (std::vector<Bexpression*>::const_iterator pcv = pc->begin();
441 tree t = (*pcv)->get_tree();
442 if (t == error_mark_node)
443 return this->error_statement();
444 source_location loc = EXPR_LOCATION(t);
445 tree label = create_artificial_label(loc);
446 tree c = build3_loc(loc, CASE_LABEL_EXPR, void_type_node,
447 (*pcv)->get_tree(), NULL_TREE, label);
448 append_to_statement_list(c, &stmt_list);
454 tree t = (*ps)->get_tree();
455 if (t == error_mark_node)
456 return this->error_statement();
457 append_to_statement_list(t, &stmt_list);
461 tree tv = value->get_tree();
462 if (tv == error_mark_node)
463 return this->error_statement();
464 tree t = build3_loc(switch_location, SWITCH_EXPR, void_type_node,
465 tv, stmt_list, NULL_TREE);
466 return this->make_statement(t);
469 // Pair of statements.
472 Gcc_backend::compound_statement(Bstatement* s1, Bstatement* s2)
474 tree stmt_list = NULL_TREE;
475 tree t = s1->get_tree();
476 if (t == error_mark_node)
477 return this->error_statement();
478 append_to_statement_list(t, &stmt_list);
480 if (t == error_mark_node)
481 return this->error_statement();
482 append_to_statement_list(t, &stmt_list);
483 return this->make_statement(stmt_list);
486 // List of statements.
489 Gcc_backend::statement_list(const std::vector<Bstatement*>& statements)
491 tree stmt_list = NULL_TREE;
492 for (std::vector<Bstatement*>::const_iterator p = statements.begin();
493 p != statements.end();
496 tree t = (*p)->get_tree();
497 if (t == error_mark_node)
498 return this->error_statement();
499 append_to_statement_list(t, &stmt_list);
501 return this->make_statement(stmt_list);
504 // Make a block. For some reason gcc uses a dual structure for
505 // blocks: BLOCK tree nodes and BIND_EXPR tree nodes. Since the
506 // BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in
510 Gcc_backend::block(Bfunction* function, Bblock* enclosing,
511 const std::vector<Bvariable*>& vars,
512 source_location start_location,
515 tree block_tree = make_node(BLOCK);
516 if (enclosing == NULL)
518 // FIXME: Permitting FUNCTION to be NULL is a temporary measure
519 // until we have a proper representation of the init function.
521 if (function == NULL)
522 fndecl = current_function_decl;
524 fndecl = function->get_tree();
525 gcc_assert(fndecl != NULL_TREE);
527 // We may have already created a block for local variables when
528 // we take the address of a parameter.
529 if (DECL_INITIAL(fndecl) == NULL_TREE)
531 BLOCK_SUPERCONTEXT(block_tree) = fndecl;
532 DECL_INITIAL(fndecl) = block_tree;
536 tree superblock_tree = DECL_INITIAL(fndecl);
537 BLOCK_SUPERCONTEXT(block_tree) = superblock_tree;
539 for (pp = &BLOCK_SUBBLOCKS(superblock_tree);
541 pp = &BLOCK_CHAIN(*pp))
548 tree superbind_tree = enclosing->get_tree();
549 tree superblock_tree = BIND_EXPR_BLOCK(superbind_tree);
550 gcc_assert(TREE_CODE(superblock_tree) == BLOCK);
552 BLOCK_SUPERCONTEXT(block_tree) = superblock_tree;
554 for (pp = &BLOCK_SUBBLOCKS(superblock_tree);
556 pp = &BLOCK_CHAIN(*pp))
561 tree* pp = &BLOCK_VARS(block_tree);
562 for (std::vector<Bvariable*>::const_iterator pv = vars.begin();
566 *pp = (*pv)->get_tree();
567 if (*pp != error_mark_node)
568 pp = &DECL_CHAIN(*pp);
572 TREE_USED(block_tree) = 1;
574 tree bind_tree = build3_loc(start_location, BIND_EXPR, void_type_node,
575 BLOCK_VARS(block_tree), NULL_TREE, block_tree);
576 TREE_SIDE_EFFECTS(bind_tree) = 1;
578 return new Bblock(bind_tree);
581 // Add statements to a block.
584 Gcc_backend::block_add_statements(Bblock* bblock,
585 const std::vector<Bstatement*>& statements)
587 tree stmt_list = NULL_TREE;
588 for (std::vector<Bstatement*>::const_iterator p = statements.begin();
589 p != statements.end();
592 tree s = (*p)->get_tree();
593 if (s != error_mark_node)
594 append_to_statement_list(s, &stmt_list);
597 tree bind_tree = bblock->get_tree();
598 gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR);
599 BIND_EXPR_BODY(bind_tree) = stmt_list;
602 // Return a block as a statement.
605 Gcc_backend::block_statement(Bblock* bblock)
607 tree bind_tree = bblock->get_tree();
608 gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR);
609 return this->make_statement(bind_tree);
612 // Make a global variable.
615 Gcc_backend::global_variable(const std::string& package_name,
616 const std::string& unique_prefix,
617 const std::string& name,
621 source_location location)
623 tree type_tree = btype->get_tree();
624 if (type_tree == error_mark_node)
625 return this->error_variable();
627 std::string var_name(package_name);
628 var_name.push_back('.');
629 var_name.append(name);
630 tree decl = build_decl(location, VAR_DECL,
631 get_identifier_from_string(var_name),
634 DECL_EXTERNAL(decl) = 1;
636 TREE_STATIC(decl) = 1;
639 TREE_PUBLIC(decl) = 1;
641 std::string asm_name(unique_prefix);
642 asm_name.push_back('.');
643 asm_name.append(var_name);
644 SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
648 go_preserve_from_gc(decl);
650 return new Bvariable(decl);
653 // Set the initial value of a global variable.
656 Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr)
658 tree expr_tree = expr->get_tree();
659 if (expr_tree == error_mark_node)
661 gcc_assert(TREE_CONSTANT(expr_tree));
662 tree var_decl = var->get_tree();
663 if (var_decl == error_mark_node)
665 DECL_INITIAL(var_decl) = expr_tree;
668 // Make a local variable.
671 Gcc_backend::local_variable(Bfunction* function, const std::string& name,
672 Btype* btype, source_location location)
674 tree type_tree = btype->get_tree();
675 if (type_tree == error_mark_node)
676 return this->error_variable();
677 tree decl = build_decl(location, VAR_DECL,
678 get_identifier_from_string(name),
680 DECL_CONTEXT(decl) = function->get_tree();
682 go_preserve_from_gc(decl);
683 return new Bvariable(decl);
686 // Make a function parameter variable.
689 Gcc_backend::parameter_variable(Bfunction* function, const std::string& name,
690 Btype* btype, source_location location)
692 tree type_tree = btype->get_tree();
693 if (type_tree == error_mark_node)
694 return this->error_variable();
695 tree decl = build_decl(location, PARM_DECL,
696 get_identifier_from_string(name),
698 DECL_CONTEXT(decl) = function->get_tree();
699 DECL_ARG_TYPE(decl) = type_tree;
701 go_preserve_from_gc(decl);
702 return new Bvariable(decl);
708 Gcc_backend::label(Bfunction* function, const std::string& name,
709 source_location location)
713 decl = create_artificial_label(location);
716 tree id = get_identifier_from_string(name);
717 decl = build_decl(location, LABEL_DECL, id, void_type_node);
718 DECL_CONTEXT(decl) = function->get_tree();
720 return new Blabel(decl);
723 // Make a statement which defines a label.
726 Gcc_backend::label_definition_statement(Blabel* label)
728 tree lab = label->get_tree();
729 tree ret = fold_build1_loc(DECL_SOURCE_LOCATION(lab), LABEL_EXPR,
730 void_type_node, lab);
731 return this->make_statement(ret);
734 // Make a goto statement.
737 Gcc_backend::goto_statement(Blabel* label, source_location location)
739 tree lab = label->get_tree();
740 tree ret = fold_build1_loc(location, GOTO_EXPR, void_type_node, lab);
741 return this->make_statement(ret);
744 // Get the address of a label.
747 Gcc_backend::label_address(Blabel* label, source_location location)
749 tree lab = label->get_tree();
751 TREE_ADDRESSABLE(lab) = 1;
752 tree ret = fold_convert_loc(location, ptr_type_node,
753 build_fold_addr_expr_loc(location, lab));
754 return this->make_expression(ret);
757 // The single backend.
759 static Gcc_backend gcc_backend;
761 // Return the backend generator.
769 // FIXME: Temporary functions while converting to the new backend
781 return new Bexpression(t);
787 return new Bstatement(t);
791 tree_to_function(tree t)
793 return new Bfunction(t);
797 tree_to_block(tree t)
799 gcc_assert(TREE_CODE(t) == BIND_EXPR);
800 return new Bblock(t);
804 expr_to_tree(Bexpression* be)
806 return be->get_tree();
810 stat_to_tree(Bstatement* bs)
812 return bs->get_tree();
816 block_to_tree(Bblock* bb)
818 return bb->get_tree();
822 var_to_tree(Bvariable* bv)
824 return bv->get_tree();