summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/go.cc
blob: 7b1fd7eccbb4b8d7c1e279497b6e048e5fcd9810 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// go.cc -- Go frontend main file for gcc.

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "go-system.h"

#include "go-c.h"

#include "lex.h"
#include "parse.h"
#include "gogo.h"

// The unique prefix to use for exported symbols.  This is set during
// option processing.

static std::string unique_prefix;

// The data structures we build to represent the file.
static Gogo* gogo;

// Create the main IR data structure.

GO_EXTERN_C
void
go_create_gogo(int int_type_size, int pointer_size)
{
  gcc_assert(::gogo == NULL);
  ::gogo = new Gogo(int_type_size, pointer_size);
  if (!unique_prefix.empty())
    ::gogo->set_unique_prefix(unique_prefix);
}

// Set the unique prefix we use for exported symbols.

GO_EXTERN_C
void
go_set_prefix(const char* arg)
{
  unique_prefix = arg;
  for (size_t i = 0; i < unique_prefix.length(); ++i)
    {
      char c = unique_prefix[i];
      if ((c >= 'a' && c <= 'z')
	  || (c >= 'A' && c <= 'Z')
	  || (c >= '0' && c <= '9')
	  || c == '_')
	;
      else
	unique_prefix[i] = '_';
    }
}

// Parse the input files.

GO_EXTERN_C
void
go_parse_input_files(const char** filenames, unsigned int filename_count,
		     bool only_check_syntax, bool require_return_statement)
{
  gcc_assert(filename_count > 0);
  for (unsigned int i = 0; i < filename_count; ++i)
    {
      if (i > 0)
	::gogo->clear_file_scope();

      const char* filename = filenames[i];
      FILE* file;
      if (strcmp(filename, "-") == 0)
	file = stdin;
      else
	{
	  file = fopen(filename, "r");
	  if (file == NULL)
	    fatal_error("cannot open %s: %m", filename);
	}

      Lex lexer(filename, file);

      Parse parse(&lexer, ::gogo);
      parse.program();

      if (strcmp(filename, "-") != 0)
	fclose(file);
    }

  ::gogo->clear_file_scope();

  // If the global predeclared names are referenced but not defined,
  // define them now.
  ::gogo->define_global_names();

  // Finalize method lists and build stub methods for named types.
  ::gogo->finalize_methods();

  // Now that we have seen all the names, lower the parse tree into a
  // form which is easier to use.
  ::gogo->lower_parse_tree();

  // Now that we have seen all the names, verify that types are
  // correct.
  ::gogo->verify_types();

  // Work out types of unspecified constants and variables.
  ::gogo->determine_types();

  // Check types and issue errors as appropriate.
  ::gogo->check_types();

  if (only_check_syntax)
    return;

  // Check that functions have return statements.
  if (require_return_statement)
    ::gogo->check_return_statements();

  // Export global identifiers as appropriate.
  ::gogo->do_exports();

  // Turn short-cut operators (&&, ||) into explicit if statements.
  ::gogo->remove_shortcuts();

  // Use temporary variables to force order of evaluation.
  ::gogo->order_evaluations();

  // Build thunks for functions which call recover.
  ::gogo->build_recover_thunks();

  // Convert complicated go and defer statements into simpler ones.
  ::gogo->simplify_thunk_statements();
}

// Write out globals.

GO_EXTERN_C
void
go_write_globals()
{
  return ::gogo->write_globals();
}

// Return the global IR structure.  This is used by some of the
// langhooks to pass to other code.

Gogo*
go_get_gogo()
{
  return ::gogo;
}