aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/go-gcc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/go-gcc.cc')
-rw-r--r--gcc/go/go-gcc.cc94
1 files changed, 92 insertions, 2 deletions
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 2785bf2..ee100c6 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -90,6 +90,14 @@ class Bfunction : public Gcc_tree
{ }
};
+class Blabel : public Gcc_tree
+{
+ public:
+ Blabel(tree t)
+ : Gcc_tree(t)
+ { }
+};
+
// This file implements the interface between the Go frontend proper
// and the gcc IR. This implements specific instantiations of
// abstract classes defined by the Go frontend proper. The Go
@@ -158,22 +166,46 @@ class Gcc_backend : public Backend
// Statements.
- // Create an assignment statement.
Bstatement*
assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location);
- // Create a return statement.
Bstatement*
return_statement(Bfunction*, const std::vector<Bexpression*>&,
source_location);
+ // Labels.
+
+ Blabel*
+ label(Bfunction*, const std::string& name, source_location);
+
+ Bstatement*
+ label_definition_statement(Blabel*);
+
+ Bstatement*
+ goto_statement(Blabel*, source_location);
+
+ Bexpression*
+ label_address(Blabel*, source_location);
+
private:
+ // Make a Bexpression from a tree.
+ Bexpression*
+ make_expression(tree t)
+ { return new Bexpression(t); }
+
// Make a Bstatement from a tree.
Bstatement*
make_statement(tree t)
{ return new Bstatement(t); }
};
+// A helper function.
+
+static inline tree
+get_identifier_from_string(const std::string& str)
+{
+ return get_identifier_with_length(str.data(), str.length());
+}
// Assignment.
Bstatement*
@@ -249,6 +281,58 @@ Gcc_backend::return_statement(Bfunction* bfunction,
return this->make_statement(ret);
}
+// Make a label.
+
+Blabel*
+Gcc_backend::label(Bfunction* function, const std::string& name,
+ source_location location)
+{
+ tree decl;
+ if (name.empty())
+ decl = create_artificial_label(location);
+ else
+ {
+ tree id = get_identifier_from_string(name);
+ decl = build_decl(location, LABEL_DECL, id, void_type_node);
+ DECL_CONTEXT(decl) = function->get_tree();
+ }
+ return new Blabel(decl);
+}
+
+// Make a statement which defines a label.
+
+Bstatement*
+Gcc_backend::label_definition_statement(Blabel* label)
+{
+ tree lab = label->get_tree();
+ tree ret = fold_build1_loc(DECL_SOURCE_LOCATION(lab), LABEL_EXPR,
+ void_type_node, lab);
+ return this->make_statement(ret);
+}
+
+// Make a goto statement.
+
+Bstatement*
+Gcc_backend::goto_statement(Blabel* label, source_location location)
+{
+ tree lab = label->get_tree();
+ tree ret = fold_build1_loc(location, GOTO_EXPR, void_type_node, lab);
+ return this->make_statement(ret);
+}
+
+// Get the address of a label.
+
+Bexpression*
+Gcc_backend::label_address(Blabel* label, source_location location)
+{
+ tree lab = label->get_tree();
+ TREE_USED(lab) = 1;
+ TREE_ADDRESSABLE(lab) = 1;
+ tree ret = fold_convert_loc(location, ptr_type_node,
+ build_fold_addr_expr_loc(location, lab));
+ return this->make_expression(ret);
+}
+
// The single backend.
static Gcc_backend gcc_backend;
@@ -277,6 +361,12 @@ tree_to_function(tree t)
}
tree
+expression_to_tree(Bexpression* be)
+{
+ return be->get_tree();
+}
+
+tree
statement_to_tree(Bstatement* bs)
{
return bs->get_tree();