From 9fec18623e1a937863f86cc25fa855e65e91d473 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 2 May 2020 18:19:32 +0100 Subject: This sets up the conversion from AST to GCC It will crash when compiling but its the code setup i want to get in sooner than later. Addresses #15 --- gcc/rust/Make-lang.in | 8 +- gcc/rust/backend.h | 758 -------------------------------------- gcc/rust/backend/rust-compile.cc | 647 +++++++++++++++++++++++++++++++++ gcc/rust/backend/rust-compile.h | 246 +++++++++++++ gcc/rust/rust-backend.h | 761 +++++++++++++++++++++++++++++++++++++++ gcc/rust/rust-gcc.cc | 295 +-------------- gcc/rust/rust-lang.cc | 3 +- gcc/rust/rust-session-manager.cc | 9 + gcc/rust/rust-session-manager.h | 393 +++++++++++--------- 9 files changed, 1887 insertions(+), 1233 deletions(-) delete mode 100644 gcc/rust/backend.h create mode 100644 gcc/rust/backend/rust-compile.cc create mode 100644 gcc/rust/backend/rust-compile.h create mode 100644 gcc/rust/rust-backend.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index e35aa69..0b867a4 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -70,6 +70,7 @@ GRS_OBJS = \ rust/rust-ast-full-test.o \ rust/rust-session-manager.o \ rust/rust-resolution.o \ + rust/rust-compile.o \ $(END) # removed object files from here @@ -209,7 +210,7 @@ CFLAGS-rust/rust-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \ -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" # cross-folder includes - add new folders later -RUST_INCLUDES = -I $(srcdir)/rust -I $(srcdir)/rust/lex -I $(srcdir)/rust/parse -I $(srcdir)/rust/ast -I $(srcdir)/rust/analysis +RUST_INCLUDES = -I $(srcdir)/rust -I $(srcdir)/rust/lex -I $(srcdir)/rust/parse -I $(srcdir)/rust/ast -I $(srcdir)/rust/analysis -I $(srcdir)/rust/backend # add files that require cross-folder includes - currently rust-lang.o, rust-lex.o CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) @@ -238,3 +239,8 @@ rust/%.o: rust/ast/%.cc rust/%.o: rust/analysis/%.cc $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< $(POSTCOMPILE) + +# build rust/backend files in rust folder +rust/%.o: rust/backend/%.cc + $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< + $(POSTCOMPILE) diff --git a/gcc/rust/backend.h b/gcc/rust/backend.h deleted file mode 100644 index 8454847..0000000 --- a/gcc/rust/backend.h +++ /dev/null @@ -1,758 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "operator.h" - -// TODO: Will have to be significantly modified to work with Rust and current -// setup of gccrs - -// Pointers to these types are created by the backend, passed to the -// frontend, and passed back to the backend. The types must be -// defined by the backend using these names. - -// The backend representation of a type. -class Btype; - -// The backend represention of an expression. -class Bexpression; - -// The backend representation of a statement. -class Bstatement; - -// The backend representation of a function definition or declaration. -class Bfunction; - -// The backend representation of a block. -class Bblock; - -// The backend representation of a variable. -class Bvariable; - -// The backend representation of a label. -class Blabel; - -// The backend interface. This is a pure abstract class that a -// specific backend will implement. - -class Backend -{ -public: - virtual ~Backend () {} - - // Name/type/location. Used for function parameters, struct fields, - // interface methods. - struct Btyped_identifier - { - std::string name; - Btype *btype; - Location location; - - Btyped_identifier () - : name (), btype (NULL), location (Linemap::unknown_location ()) - {} - - Btyped_identifier (const std::string &a_name, Btype *a_btype, - Location a_location) - : name (a_name), btype (a_btype), location (a_location) - {} - }; - - // Types. - - // Produce an error type. Actually the backend could probably just - // crash if this is called. - virtual Btype *error_type () = 0; - - // Get a void type. This is used in (at least) two ways: 1) as the - // return type of a function with no result parameters; 2) - // unsafe.Pointer is represented as *void. - virtual Btype *void_type () = 0; - - // Get the unnamed boolean type. - virtual Btype *bool_type () = 0; - - // Get an unnamed integer type with the given signedness and number - // of bits. - virtual Btype *integer_type (bool is_unsigned, int bits) = 0; - - // Get an unnamed floating point type with the given number of bits - // (32 or 64). - virtual Btype *float_type (int bits) = 0; - - // Get an unnamed complex type with the given number of bits (64 or 128). - virtual Btype *complex_type (int bits) = 0; - - // Get a pointer type. - virtual Btype *pointer_type (Btype *to_type) = 0; - - // Get a function type. The receiver, parameter, and results are - // generated from the types in the Function_type. The Function_type - // is provided so that the names are available. This should return - // not the type of a Go function (which is a pointer to a struct) - // but the type of a C function pointer (which will be used as the - // type of the first field of the struct). If there is more than - // one result, RESULT_STRUCT is a struct type to hold the results, - // and RESULTS may be ignored; if there are zero or one results, - // RESULT_STRUCT is NULL. - virtual Btype * - function_type (const Btyped_identifier &receiver, - const std::vector ¶meters, - const std::vector &results, - Btype *result_struct, Location location) - = 0; - - // Get a struct type. - virtual Btype *struct_type (const std::vector &fields) = 0; - - // Get an array type. - virtual Btype *array_type (Btype *element_type, Bexpression *length) = 0; - - // Create a placeholder pointer type. This is used for a named - // pointer type, since in Go a pointer type may refer to itself. - // NAME is the name of the type, and the location is where the named - // type is defined. This function is also used for unnamed function - // types with multiple results, in which case the type has no name - // and NAME will be empty. FOR_FUNCTION is true if this is for a C - // pointer to function type. A Go func type is represented as a - // pointer to a struct, and the first field of the struct is a C - // pointer to function. The return value will later be passed as - // the first parameter to set_placeholder_pointer_type or - // set_placeholder_function_type. - virtual Btype *placeholder_pointer_type (const std::string &name, Location, - bool for_function) - = 0; - - // Fill in a placeholder pointer type as a pointer. This takes a - // type returned by placeholder_pointer_type and arranges for it to - // point to the type that TO_TYPE points to (that is, PLACEHOLDER - // becomes the same type as TO_TYPE). Returns true on success, - // false on failure. - virtual bool set_placeholder_pointer_type (Btype *placeholder, Btype *to_type) - = 0; - - // Fill in a placeholder pointer type as a function. This takes a - // type returned by placeholder_pointer_type and arranges for it to - // become a real Go function type (which corresponds to a C/C++ - // pointer to function type). FT will be something returned by the - // function_type method. Returns true on success, false on failure. - virtual bool set_placeholder_function_type (Btype *placeholder, Btype *ft) - = 0; - - // Create a placeholder struct type. This is used for a named - // struct type, as with placeholder_pointer_type. It is also used - // for interface types, in which case NAME will be the empty string. - virtual Btype *placeholder_struct_type (const std::string &name, Location) - = 0; - - // Fill in a placeholder struct type. This takes a type returned by - // placeholder_struct_type and arranges for it to become a real - // struct type. The parameter is as for struct_type. Returns true - // on success, false on failure. - virtual bool - set_placeholder_struct_type (Btype *placeholder, - const std::vector &fields) - = 0; - - // Create a placeholder array type. This is used for a named array - // type, as with placeholder_pointer_type, to handle cases like - // type A []*A. - virtual Btype *placeholder_array_type (const std::string &name, Location) = 0; - - // Fill in a placeholder array type. This takes a type returned by - // placeholder_array_type and arranges for it to become a real array - // type. The parameters are as for array_type. Returns true on - // success, false on failure. - virtual bool set_placeholder_array_type (Btype *placeholder, - Btype *element_type, - Bexpression *length) - = 0; - - // Return a named version of a type. The location is the location - // of the type definition. This will not be called for a type - // created via placeholder_pointer_type, placeholder_struct_type, or - // placeholder_array_type.. (It may be called for a pointer, - // struct, or array type in a case like "type P *byte; type Q P".) - virtual Btype *named_type (const std::string &name, Btype *, Location) = 0; - - // Create a marker for a circular pointer type. Go pointer and - // function types can refer to themselves in ways that are not - // permitted in C/C++. When a circular type is found, this function - // is called for the circular reference. This permits the backend - // to decide how to handle such a type. PLACEHOLDER is the - // placeholder type which has already been created; if the backend - // is prepared to handle a circular pointer type, it may simply - // return PLACEHOLDER. FOR_FUNCTION is true if this is for a - // function type. - // - // For "type P *P" the sequence of calls will be - // bt1 = placeholder_pointer_type(); - // bt2 = circular_pointer_type(bt1, false); - // set_placeholder_pointer_type(bt1, bt2); - virtual Btype *circular_pointer_type (Btype *placeholder, bool for_function) - = 0; - - // Return whether the argument could be a special type created by - // circular_pointer_type. This is used to introduce explicit type - // conversions where needed. If circular_pointer_type returns its - // PLACEHOLDER parameter, this may safely always return false. - virtual bool is_circular_pointer_type (Btype *) = 0; - - // Return the size of a type. - virtual int64_t type_size (Btype *) = 0; - - // Return the alignment of a type. - virtual int64_t type_alignment (Btype *) = 0; - - // Return the alignment of a struct field of this type. This is - // normally the same as type_alignment, but not always. - virtual int64_t type_field_alignment (Btype *) = 0; - - // Return the offset of field INDEX in a struct type. INDEX is the - // entry in the FIELDS std::vector parameter of struct_type or - // set_placeholder_struct_type. - virtual int64_t type_field_offset (Btype *, size_t index) = 0; - - // Expressions. - - // Return an expression for a zero value of the given type. This is - // used for cases such as local variable initialization and - // converting nil to other types. - virtual Bexpression *zero_expression (Btype *) = 0; - - // Create an error expression. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bexpression *error_expression () = 0; - - // Create a nil pointer expression. - virtual Bexpression *nil_pointer_expression () = 0; - - // Create a reference to a variable. - virtual Bexpression *var_expression (Bvariable *var, Location) = 0; - - // Create an expression that indirects through the pointer expression EXPR - // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer - // is known to point to a valid memory location. BTYPE is the expected type - // of the indirected EXPR. - virtual Bexpression *indirect_expression (Btype *btype, Bexpression *expr, - bool known_valid, Location) - = 0; - - // Return an expression that declares a constant named NAME with the - // constant value VAL in BTYPE. - virtual Bexpression *named_constant_expression (Btype *btype, - const std::string &name, - Bexpression *val, Location) - = 0; - - // Return an expression for the multi-precision integer VAL in BTYPE. - virtual Bexpression *integer_constant_expression (Btype *btype, mpz_t val) - = 0; - - // Return an expression for the floating point value VAL in BTYPE. - virtual Bexpression *float_constant_expression (Btype *btype, mpfr_t val) = 0; - - // Return an expression for the complex value VAL in BTYPE. - virtual Bexpression *complex_constant_expression (Btype *btype, mpc_t val) - = 0; - - // Return an expression for the string value VAL. - virtual Bexpression *string_constant_expression (const std::string &val) = 0; - - // Return an expression for the boolean value VAL. - virtual Bexpression *boolean_constant_expression (bool val) = 0; - - // Return an expression for the real part of BCOMPLEX. - virtual Bexpression *real_part_expression (Bexpression *bcomplex, Location) - = 0; - - // Return an expression for the imaginary part of BCOMPLEX. - virtual Bexpression *imag_part_expression (Bexpression *bcomplex, Location) - = 0; - - // Return an expression for the complex number (BREAL, BIMAG). - virtual Bexpression *complex_expression (Bexpression *breal, - Bexpression *bimag, Location) - = 0; - - // Return an expression that converts EXPR to TYPE. - virtual Bexpression *convert_expression (Btype *type, Bexpression *expr, - Location) - = 0; - - // Create an expression for the address of a function. This is used to - // get the address of the code for a function. - virtual Bexpression *function_code_expression (Bfunction *, Location) = 0; - - // Create an expression that takes the address of an expression. - virtual Bexpression *address_expression (Bexpression *, Location) = 0; - - // Return an expression for the field at INDEX in BSTRUCT. - virtual Bexpression *struct_field_expression (Bexpression *bstruct, - size_t index, Location) - = 0; - - // Create an expression that executes BSTAT before BEXPR. - virtual Bexpression *compound_expression (Bstatement *bstat, - Bexpression *bexpr, Location) - = 0; - - // Return an expression that executes THEN_EXPR if CONDITION is true, or - // ELSE_EXPR otherwise and returns the result as type BTYPE, within the - // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. - virtual Bexpression * - conditional_expression (Bfunction *function, Btype *btype, - Bexpression *condition, Bexpression *then_expr, - Bexpression *else_expr, Location) - = 0; - - // Return an expression for the unary operation OP EXPR. - // Supported values of OP are (from operators.h): - // MINUS, NOT, XOR. - virtual Bexpression *unary_expression (Operator op, Bexpression *expr, - Location) - = 0; - - // Return an expression for the binary operation LEFT OP RIGHT. - // Supported values of OP are (from operators.h): - // EQEQ, NOTEQ, LT, LE, GT, GE, PLUS, MINUS, OR, XOR, MULT, DIV, MOD, - // LSHIFT, RSHIFT, AND, NOT. - virtual Bexpression *binary_expression (Operator op, Bexpression *left, - Bexpression *right, Location) - = 0; - - // Return an expression that constructs BTYPE with VALS. BTYPE must be the - // backend representation a of struct. VALS must be in the same order as the - // corresponding fields in BTYPE. - virtual Bexpression * - constructor_expression (Btype *btype, const std::vector &vals, - Location) - = 0; - - // Return an expression that constructs an array of BTYPE with INDEXES and - // VALS. INDEXES and VALS must have the same amount of elements. Each index - // in INDEXES must be in the same order as the corresponding value in VALS. - virtual Bexpression *array_constructor_expression ( - Btype *btype, const std::vector &indexes, - const std::vector &vals, Location) - = 0; - - // Return an expression for the address of BASE[INDEX]. - // BASE has a pointer type. This is used for slice indexing. - virtual Bexpression *pointer_offset_expression (Bexpression *base, - Bexpression *index, Location) - = 0; - - // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid - // fixed-length array, not a slice. - virtual Bexpression *array_index_expression (Bexpression *array, - Bexpression *index, Location) - = 0; - - // Create an expression for a call to FN with ARGS, taking place within - // caller CALLER. - virtual Bexpression *call_expression (Bfunction *caller, Bexpression *fn, - const std::vector &args, - Bexpression *static_chain, Location) - = 0; - - // Statements. - - // Create an error statement. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bstatement *error_statement () = 0; - - // Create an expression statement within the specified function. - virtual Bstatement *expression_statement (Bfunction *, Bexpression *) = 0; - - // Create a variable initialization statement in the specified - // function. This initializes a local variable at the point in the - // program flow where it is declared. - virtual Bstatement *init_statement (Bfunction *, Bvariable *var, - Bexpression *init) - = 0; - - // Create an assignment statement within the specified function. - virtual Bstatement *assignment_statement (Bfunction *, Bexpression *lhs, - Bexpression *rhs, Location) - = 0; - - // Create a return statement, passing the representation of the - // function and the list of values to return. - virtual Bstatement * - return_statement (Bfunction *, const std::vector &, Location) - = 0; - - // Create an if statement within a function. ELSE_BLOCK may be NULL. - virtual Bstatement *if_statement (Bfunction *, Bexpression *condition, - Bblock *then_block, Bblock *else_block, - Location) - = 0; - - // Create a switch statement where the case values are constants. - // CASES and STATEMENTS must have the same number of entries. If - // VALUE matches any of the list in CASES[i], which will all be - // integers, then STATEMENTS[i] is executed. STATEMENTS[i] will - // either end with a goto statement or will fall through into - // STATEMENTS[i + 1]. CASES[i] is empty for the default clause, - // which need not be last. FUNCTION is the current function. - virtual Bstatement * - switch_statement (Bfunction *function, Bexpression *value, - const std::vector > &cases, - const std::vector &statements, Location) - = 0; - - // Create a single statement from two statements. - virtual Bstatement *compound_statement (Bstatement *, Bstatement *) = 0; - - // Create a single statement from a list of statements. - virtual Bstatement *statement_list (const std::vector &) = 0; - - // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if - // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and - // if not NULL, it will always be executed. This is used for handling defers - // in Go functions. In C++, the resulting code is of this form: - // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } - virtual Bstatement * - exception_handler_statement (Bstatement *bstat, Bstatement *except_stmt, - Bstatement *finally_stmt, Location) - = 0; - - // Blocks. - - // Create a block. The frontend will call this function when it - // starts converting a block within a function. FUNCTION is the - // current function. ENCLOSING is the enclosing block; it will be - // NULL for the top-level block in a function. VARS is the list of - // local variables defined within this block; each entry will be - // created by the local_variable function. START_LOCATION is the - // location of the start of the block, more or less the location of - // the initial curly brace. END_LOCATION is the location of the end - // of the block, more or less the location of the final curly brace. - // The statements will be added after the block is created. - virtual Bblock *block (Bfunction *function, Bblock *enclosing, - const std::vector &vars, - Location start_location, Location end_location) - = 0; - - // Add the statements to a block. The block is created first. Then - // the statements are created. Then the statements are added to the - // block. This will called exactly once per block. The vector may - // be empty if there are no statements. - virtual void block_add_statements (Bblock *, - const std::vector &) - = 0; - - // Return the block as a statement. This is used to include a block - // in a list of statements. - virtual Bstatement *block_statement (Bblock *) = 0; - - // Variables. - - // Create an error variable. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bvariable *error_variable () = 0; - - // Create a global variable. NAME is the package-qualified name of - // the variable. ASM_NAME is the encoded identifier for the - // variable, incorporating the package, and made safe for the - // assembler. BTYPE is the type of the variable. IS_EXTERNAL is - // true if the variable is defined in some other package. IS_HIDDEN - // is true if the variable is not exported (name begins with a lower - // case letter). IN_UNIQUE_SECTION is true if the variable should - // be put into a unique section if possible; this is intended to - // permit the linker to garbage collect the variable if it is not - // referenced. LOCATION is where the variable was defined. - virtual Bvariable *global_variable (const std::string &name, - const std::string &asm_name, Btype *btype, - bool is_external, bool is_hidden, - bool in_unique_section, Location location) - = 0; - - // A global variable will 1) be initialized to zero, or 2) be - // initialized to a constant value, or 3) be initialized in the init - // function. In case 2, the frontend will call - // global_variable_set_init to set the initial value. If this is - // not called, the backend should initialize a global variable to 0. - // The init function may then assign a value to it. - virtual void global_variable_set_init (Bvariable *, Bexpression *) = 0; - - // Create a local variable. The frontend will create the local - // variables first, and then create the block which contains them. - // FUNCTION is the function in which the variable is defined. NAME - // is the name of the variable. TYPE is the type. DECL_VAR, if not - // null, gives the location at which the value of this variable may - // be found, typically used to create an inner-scope reference to an - // outer-scope variable, to extend the lifetime of the variable beyond - // the inner scope. IS_ADDRESS_TAKEN is true if the address of this - // variable is taken (this implies that the address does not escape - // the function, as otherwise the variable would be on the heap). - // LOCATION is where the variable is defined. For each local variable - // the frontend will call init_statement to set the initial value. - virtual Bvariable * - local_variable (Bfunction *function, const std::string &name, Btype *type, - Bvariable *decl_var, bool is_address_taken, Location location) - = 0; - - // Create a function parameter. This is an incoming parameter, not - // a result parameter (result parameters are treated as local - // variables). The arguments are as for local_variable. - virtual Bvariable * - parameter_variable (Bfunction *function, const std::string &name, Btype *type, - bool is_address_taken, Location location) - = 0; - - // Create a static chain parameter. This is the closure parameter. - virtual Bvariable *static_chain_variable (Bfunction *function, - const std::string &name, - Btype *type, Location location) - = 0; - - // Create a temporary variable. A temporary variable has no name, - // just a type. We pass in FUNCTION and BLOCK in case they are - // needed. If INIT is not NULL, the variable should be initialized - // to that value. Otherwise the initial value is irrelevant--the - // backend does not have to explicitly initialize it to zero. - // ADDRESS_IS_TAKEN is true if the programs needs to take the - // address of this temporary variable. LOCATION is the location of - // the statement or expression which requires creating the temporary - // variable, and may not be very useful. This function should - // return a variable which can be referenced later and should set - // *PSTATEMENT to a statement which initializes the variable. - virtual Bvariable * - temporary_variable (Bfunction *, Bblock *, Btype *, Bexpression *init, - bool address_is_taken, Location location, - Bstatement **pstatement) - = 0; - - // Create an implicit variable that is compiler-defined. This is - // used when generating GC data and roots, when storing the values - // of a slice constructor, and for the zero value of types. This returns a - // Bvariable because it corresponds to an initialized variable in C. - // - // NAME is the name to use for the initialized variable this will create. - // - // ASM_NAME is encoded assembler-friendly version of the name, or the - // empty string if no encoding is needed. - // - // TYPE is the type of the implicit variable. - // - // IS_HIDDEN will be true if the descriptor should only be visible - // within the current object. - // - // IS_CONSTANT is true if the implicit variable should be treated like it is - // immutable. For slice initializers, if the values must be copied to the - // heap, the variable IS_CONSTANT. - // - // IS_COMMON is true if the implicit variable should - // be treated as a common variable (multiple definitions with - // different sizes permitted in different object files, all merged - // into the largest definition at link time); this will be true for - // the zero value. IS_HIDDEN and IS_COMMON will never both be true. - // - // If ALIGNMENT is not zero, it is the desired alignment of the variable. - virtual Bvariable * - implicit_variable (const std::string &name, const std::string &asm_name, - Btype *type, bool is_hidden, bool is_constant, - bool is_common, int64_t alignment) - = 0; - - // Set the initial value of a variable created by implicit_variable. - // This must be called even if there is no initializer, i.e., INIT is NULL. - // The NAME, TYPE, IS_HIDDEN, IS_CONSTANT, and IS_COMMON parameters are - // the same ones passed to implicit_variable. INIT will be a composite - // literal of type TYPE. It will not contain any function calls or anything - // else that can not be put into a read-only data section. - // It may contain the address of variables created by implicit_variable. - // - // If IS_COMMON is true, INIT will be NULL, and the - // variable should be initialized to all zeros. - virtual void implicit_variable_set_init (Bvariable *, const std::string &name, - Btype *type, bool is_hidden, - bool is_constant, bool is_common, - Bexpression *init) - = 0; - - // Create a reference to a named implicit variable defined in some - // other package. This will be a variable created by a call to - // implicit_variable with the same NAME, ASM_NAME and TYPE and with - // IS_COMMON passed as false. This corresponds to an extern global - // variable in C. - virtual Bvariable *implicit_variable_reference (const std::string &name, - const std::string &asm_name, - Btype *type) - = 0; - - // Create a named immutable initialized data structure. This is - // used for type descriptors, map descriptors, and function - // descriptors. This returns a Bvariable because it corresponds to - // an initialized const variable in C. - // - // NAME is the name to use for the initialized global variable which - // this call will create. - // - // ASM_NAME is the encoded, assembler-friendly version of NAME, or - // the empty string if no encoding is needed. - // - // IS_HIDDEN will be true if the descriptor should only be visible - // within the current object. - // - // IS_COMMON is true if NAME may be defined by several packages, and - // the linker should merge all such definitions. If IS_COMMON is - // false, NAME should be defined in only one file. In general - // IS_COMMON will be true for the type descriptor of an unnamed type - // or a builtin type. IS_HIDDEN and IS_COMMON will never both be - // true. - // - // TYPE will be a struct type; the type of the returned expression - // must be a pointer to this struct type. - // - // We must create the named structure before we know its - // initializer, because the initializer may refer to its own - // address. After calling this the frontend will call - // immutable_struct_set_init. - virtual Bvariable * - immutable_struct (const std::string &name, const std::string &asm_name, - bool is_hidden, bool is_common, Btype *type, Location) - = 0; - - // Set the initial value of a variable created by immutable_struct. - // The NAME, IS_HIDDEN, IS_COMMON, TYPE, and location parameters are - // the same ones passed to immutable_struct. INITIALIZER will be a - // composite literal of type TYPE. It will not contain any function - // calls or anything else that can not be put into a read-only data - // section. It may contain the address of variables created by - // immutable_struct. - virtual void immutable_struct_set_init (Bvariable *, const std::string &name, - bool is_hidden, bool is_common, - Btype *type, Location, - Bexpression *initializer) - = 0; - - // Create a reference to a named immutable initialized data - // structure defined in some other package. This will be a - // structure created by a call to immutable_struct with the same - // NAME, ASM_NAME and TYPE and with IS_COMMON passed as false. This - // corresponds to an extern const global variable in C. - virtual Bvariable *immutable_struct_reference (const std::string &name, - const std::string &asm_name, - Btype *type, Location) - = 0; - - // Labels. - - // Create a new label. NAME will be empty if this is a label - // created by the frontend for a loop construct. The location is - // where the label is defined. - virtual Blabel *label (Bfunction *, const std::string &name, Location) = 0; - - // Create a statement which defines a label. This statement will be - // put into the codestream at the point where the label should be - // defined. - virtual Bstatement *label_definition_statement (Blabel *) = 0; - - // Create a goto statement to a label. - virtual Bstatement *goto_statement (Blabel *, Location) = 0; - - // Create an expression for the address of a label. This is used to - // get the return address of a deferred function which may call - // recover. - virtual Bexpression *label_address (Blabel *, Location) = 0; - - // Functions. - - // Create an error function. This is used for cases which should - // not occur in a correct program, in order to keep the compilation - // going without crashing. - virtual Bfunction *error_function () = 0; - - // Bit flags to pass to the function method. - - // Set if the function should be visible outside of the current - // compilation unit. - static const unsigned int function_is_visible = 1 << 0; - - // Set if this is a function declaration rather than a definition; - // the definition will be in another compilation unit. - static const unsigned int function_is_declaration = 1 << 1; - - // Set if the function can be inlined. This is normally set, but is - // false for functions that may not be inlined because they call - // recover and must be visible for correct panic recovery. - static const unsigned int function_is_inlinable = 1 << 2; - - // Set if the function may not split the stack. This is set for the - // implementation of recover itself, among other things. - static const unsigned int function_no_split_stack = 1 << 3; - - // Set if the function does not return. This is set for the - // implementation of panic. - static const unsigned int function_does_not_return = 1 << 4; - - // Set if the function should be put in a unique section if - // possible. This is used for field tracking. - static const unsigned int function_in_unique_section = 1 << 5; - - // Set if the function should be available for inlining in the - // backend, but should not be emitted as a standalone function. Any - // call to the function that is not inlined should be treated as a - // call to a function defined in a different compilation unit. This - // is like a C99 function marked inline but not extern. - static const unsigned int function_only_inline = 1 << 6; - - // Declare or define a function of FNTYPE. - // NAME is the Go name of the function. ASM_NAME, if not the empty - // string, is the name that should be used in the symbol table; this - // will be non-empty if a magic extern comment is used. FLAGS is - // bit flags described above. - virtual Bfunction *function (Btype *fntype, const std::string &name, - const std::string &asm_name, unsigned int flags, - Location) - = 0; - - // Create a statement that runs all deferred calls for FUNCTION. This should - // be a statement that looks like this in C++: - // finish: - // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } - virtual Bstatement * - function_defer_statement (Bfunction *function, Bexpression *undefer, - Bexpression *check_defer, Location) - = 0; - - // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. - // This will only be called for a function definition. Returns true on - // success, false on failure. - virtual bool - function_set_parameters (Bfunction *function, - const std::vector ¶m_vars) - = 0; - - // Set the function body for FUNCTION using the code in CODE_STMT. Returns - // true on success, false on failure. - virtual bool function_set_body (Bfunction *function, Bstatement *code_stmt) - = 0; - - // Look up a named built-in function in the current backend implementation. - // Returns NULL if no built-in function by that name exists. - virtual Bfunction *lookup_builtin (const std::string &) = 0; - - // Utility. - - // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, - // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. - virtual void - write_global_definitions (const std::vector &type_decls, - const std::vector &constant_decls, - const std::vector &function_decls, - const std::vector &variable_decls) - = 0; - - // Write SIZE bytes of export data from BYTES to the proper - // section in the output object file. - virtual void write_export_data (const char *bytes, unsigned int size) = 0; -}; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc new file mode 100644 index 0000000..4ed9641 --- /dev/null +++ b/gcc/rust/backend/rust-compile.cc @@ -0,0 +1,647 @@ +#include "rust-compile.h" +#include "rust-diagnostics.h" + +namespace Rust { +namespace Compile { + +Compilation::Compilation (AST::Crate &crate, ::Backend *backend) + : scope (), crate (crate), backend (backend) +{} + +Compilation::~Compilation () {} + +bool +Compilation::Compile (AST::Crate &crate, ::Backend *backend) +{ + Compilation resolver (crate, backend); + return resolver.go (); +} + +bool +Compilation::go () +{ + scope.Push (); + for (auto &item : crate.items) + { + item->accept_vis (*this); + } + scope.Pop (); + + // Define all globally declared values. + if (!saw_errors ()) + backend->write_global_definitions (type_decls, const_decls, func_decls, + var_decls); + + return true; +} + +void +Compilation::visit (AST::Token &tok) +{} + +void +Compilation::visit (AST::DelimTokenTree &delim_tok_tree) +{} + +void +Compilation::visit (AST::AttrInputMetaItemContainer &input) +{} + +void +Compilation::visit (AST::IdentifierExpr &ident_expr) +{} + +void +Compilation::visit (AST::Lifetime &lifetime) +{} + +void +Compilation::visit (AST::LifetimeParam &lifetime_param) +{} + +void +Compilation::visit (AST::MacroInvocationSemi ¯o) +{} + +// rust-path.h +void +Compilation::visit (AST::PathInExpression &path) +{} +void +Compilation::visit (AST::TypePathSegment &segment) +{} +void +Compilation::visit (AST::TypePathSegmentGeneric &segment) +{} +void +Compilation::visit (AST::TypePathSegmentFunction &segment) +{} +void +Compilation::visit (AST::TypePath &path) +{} +void +Compilation::visit (AST::QualifiedPathInExpression &path) +{} +void +Compilation::visit (AST::QualifiedPathInType &path) +{} + +// rust-expr.h +void +Compilation::visit (AST::LiteralExpr &expr) +{} +void +Compilation::visit (AST::AttrInputLiteral &attr_input) +{} +void +Compilation::visit (AST::MetaItemLitExpr &meta_item) +{} +void +Compilation::visit (AST::MetaItemPathLit &meta_item) +{} +void +Compilation::visit (AST::BorrowExpr &expr) +{} +void +Compilation::visit (AST::DereferenceExpr &expr) +{} +void +Compilation::visit (AST::ErrorPropagationExpr &expr) +{} +void +Compilation::visit (AST::NegationExpr &expr) +{} +void +Compilation::visit (AST::ArithmeticOrLogicalExpr &expr) +{} +void +Compilation::visit (AST::ComparisonExpr &expr) +{} +void +Compilation::visit (AST::LazyBooleanExpr &expr) +{} +void +Compilation::visit (AST::TypeCastExpr &expr) +{} +void +Compilation::visit (AST::AssignmentExpr &expr) +{} +void +Compilation::visit (AST::CompoundAssignmentExpr &expr) +{} +void +Compilation::visit (AST::GroupedExpr &expr) +{} +// void Compilation::visit(ArrayElems& elems) {} +void +Compilation::visit (AST::ArrayElemsValues &elems) +{} +void +Compilation::visit (AST::ArrayElemsCopied &elems) +{} +void +Compilation::visit (AST::ArrayExpr &expr) +{} +void +Compilation::visit (AST::ArrayIndexExpr &expr) +{} +void +Compilation::visit (AST::TupleExpr &expr) +{} +void +Compilation::visit (AST::TupleIndexExpr &expr) +{} +void +Compilation::visit (AST::StructExprStruct &expr) +{} +// void Compilation::visit(StructExprField& field) {} +void +Compilation::visit (AST::StructExprFieldIdentifier &field) +{} +void +Compilation::visit (AST::StructExprFieldIdentifierValue &field) +{} +void +Compilation::visit (AST::StructExprFieldIndexValue &field) +{} +void +Compilation::visit (AST::StructExprStructFields &expr) +{} +void +Compilation::visit (AST::StructExprStructBase &expr) +{} +void +Compilation::visit (AST::StructExprTuple &expr) +{} +void +Compilation::visit (AST::StructExprUnit &expr) +{} +// void Compilation::visit(EnumExprField& field) {} +void +Compilation::visit (AST::EnumExprFieldIdentifier &field) +{} +void +Compilation::visit (AST::EnumExprFieldIdentifierValue &field) +{} +void +Compilation::visit (AST::EnumExprFieldIndexValue &field) +{} +void +Compilation::visit (AST::EnumExprStruct &expr) +{} +void +Compilation::visit (AST::EnumExprTuple &expr) +{} +void +Compilation::visit (AST::EnumExprFieldless &expr) +{} +void +Compilation::visit (AST::CallExpr &expr) +{} +void +Compilation::visit (AST::MethodCallExpr &expr) +{} +void +Compilation::visit (AST::FieldAccessExpr &expr) +{} +void +Compilation::visit (AST::ClosureExprInner &expr) +{} +void +Compilation::visit (AST::BlockExpr &expr) +{} +void +Compilation::visit (AST::ClosureExprInnerTyped &expr) +{} +void +Compilation::visit (AST::ContinueExpr &expr) +{} +void +Compilation::visit (AST::BreakExpr &expr) +{} +void +Compilation::visit (AST::RangeFromToExpr &expr) +{} +void +Compilation::visit (AST::RangeFromExpr &expr) +{} +void +Compilation::visit (AST::RangeToExpr &expr) +{} +void +Compilation::visit (AST::RangeFullExpr &expr) +{} +void +Compilation::visit (AST::RangeFromToInclExpr &expr) +{} +void +Compilation::visit (AST::RangeToInclExpr &expr) +{} +void +Compilation::visit (AST::ReturnExpr &expr) +{} +void +Compilation::visit (AST::UnsafeBlockExpr &expr) +{} +void +Compilation::visit (AST::LoopExpr &expr) +{} +void +Compilation::visit (AST::WhileLoopExpr &expr) +{} +void +Compilation::visit (AST::WhileLetLoopExpr &expr) +{} +void +Compilation::visit (AST::ForLoopExpr &expr) +{} +void +Compilation::visit (AST::IfExpr &expr) +{} +void +Compilation::visit (AST::IfExprConseqElse &expr) +{} +void +Compilation::visit (AST::IfExprConseqIf &expr) +{} +void +Compilation::visit (AST::IfExprConseqIfLet &expr) +{} +void +Compilation::visit (AST::IfLetExpr &expr) +{} +void +Compilation::visit (AST::IfLetExprConseqElse &expr) +{} +void +Compilation::visit (AST::IfLetExprConseqIf &expr) +{} +void +Compilation::visit (AST::IfLetExprConseqIfLet &expr) +{} +// void Compilation::visit(MatchCase& match_case) {} +void +Compilation::visit (AST::MatchCaseBlockExpr &match_case) +{} +void +Compilation::visit (AST::MatchCaseExpr &match_case) +{} +void +Compilation::visit (AST::MatchExpr &expr) +{} +void +Compilation::visit (AST::AwaitExpr &expr) +{} +void +Compilation::visit (AST::AsyncBlockExpr &expr) +{} + +// rust-item.h +void +Compilation::visit (AST::TypeParam ¶m) +{} +// void Compilation::visit(WhereClauseItem& item) {} +void +Compilation::visit (AST::LifetimeWhereClauseItem &item) +{} +void +Compilation::visit (AST::TypeBoundWhereClauseItem &item) +{} +void +Compilation::visit (AST::Method &method) +{} +void +Compilation::visit (AST::ModuleBodied &module) +{} +void +Compilation::visit (AST::ModuleNoBody &module) +{} +void +Compilation::visit (AST::ExternCrate &crate) +{} +// void Compilation::visit(UseTree& use_tree) {} +void +Compilation::visit (AST::UseTreeGlob &use_tree) +{} +void +Compilation::visit (AST::UseTreeList &use_tree) +{} +void +Compilation::visit (AST::UseTreeRebind &use_tree) +{} +void +Compilation::visit (AST::UseDeclaration &use_decl) +{} + +void +Compilation::visit (AST::Function &function) +{ + scope.Insert (function.function_name, function.return_type.get ()); + + scope.Push (); + printf ("INSIDE FUNCTION: %s\n", function.function_name.c_str ()); + + if (!function.has_function_return_type ()) + { + // TODO + // auto fntype = backend->function_type (); + + auto mangled_asm_name = ""; // TODO + currentFndecl + = backend->function (backend->void_type (), function.function_name, + mangled_asm_name, 0, function.locus); + } + else + { + translatedType = NULL; + function.return_type->accept_vis (*this); + if (translatedType == NULL) + { + rust_error_at (function.locus, "Unable to compile type"); + return; + } + + auto mangled_asm_name = ""; // TODO + currentFndecl = backend->function (translatedType, function.function_name, + mangled_asm_name, 0, function.locus); + } + + std::vector< ::Bvariable *> params; + for (auto ¶m : function.function_params) + { + printf ("FUNC PARAM: %s\n", param.as_string ().c_str ()); + // TODO + } + + if (params.size () == 0 && function.function_params.size () > 0) + { + rust_error_at (function.locus, "Unable to compile parameters"); + return; + } + else if (params.size () > 0) + { + backend->function_set_parameters (currentFndecl, params); + } + + /* + // walk the expression body + Bstatement *body; + for (auto &stmt : function.function_body->statements) + { + stmt->accept_vis (*this); + } + + backend->function_set_body (fndecl, body);*/ + + func_decls.push_back (currentFndecl); + currentFndecl = NULL; + + scope.Pop (); +} + +void +Compilation::visit (AST::TypeAlias &type_alias) +{} +void +Compilation::visit (AST::StructStruct &struct_item) +{} +void +Compilation::visit (AST::TupleStruct &tuple_struct) +{} +void +Compilation::visit (AST::EnumItem &item) +{} +void +Compilation::visit (AST::EnumItemTuple &item) +{} +void +Compilation::visit (AST::EnumItemStruct &item) +{} +void +Compilation::visit (AST::EnumItemDiscriminant &item) +{} +void +Compilation::visit (AST::Enum &enum_item) +{} +void +Compilation::visit (AST::Union &union_item) +{} +void +Compilation::visit (AST::ConstantItem &const_item) +{} +void +Compilation::visit (AST::StaticItem &static_item) +{} +void +Compilation::visit (AST::TraitItemFunc &item) +{} +void +Compilation::visit (AST::TraitItemMethod &item) +{} +void +Compilation::visit (AST::TraitItemConst &item) +{} +void +Compilation::visit (AST::TraitItemType &item) +{} +void +Compilation::visit (AST::Trait &trait) +{} +void +Compilation::visit (AST::InherentImpl &impl) +{} +void +Compilation::visit (AST::TraitImpl &impl) +{} +// void Compilation::visit(ExternalItem& item) {} +void +Compilation::visit (AST::ExternalStaticItem &item) +{} +void +Compilation::visit (AST::ExternalFunctionItem &item) +{} +void +Compilation::visit (AST::ExternBlock &block) +{} + +// rust-macro.h +void +Compilation::visit (AST::MacroMatchFragment &match) +{} +void +Compilation::visit (AST::MacroMatchRepetition &match) +{} +void +Compilation::visit (AST::MacroMatcher &matcher) +{} +void +Compilation::visit (AST::MacroRulesDefinition &rules_def) +{} +void +Compilation::visit (AST::MacroInvocation ¯o_invoc) +{} +void +Compilation::visit (AST::MetaItemPath &meta_item) +{} +void +Compilation::visit (AST::MetaItemSeq &meta_item) +{} +void +Compilation::visit (AST::MetaWord &meta_item) +{} +void +Compilation::visit (AST::MetaNameValueStr &meta_item) +{} +void +Compilation::visit (AST::MetaListPaths &meta_item) +{} +void +Compilation::visit (AST::MetaListNameValueStr &meta_item) +{} + +// rust-pattern.h +void +Compilation::visit (AST::LiteralPattern &pattern) +{ + printf ("LiteralPattern: %s\n", pattern.as_string ().c_str ()); +} + +void +Compilation::visit (AST::IdentifierPattern &pattern) +{ + printf ("IdentifierPattern: %s\n", pattern.as_string ().c_str ()); + letPatternBuffer.push_back (pattern); +} + +void +Compilation::visit (AST::WildcardPattern &pattern) +{} +// void Compilation::visit(RangePatternBound& bound) {} +void +Compilation::visit (AST::RangePatternBoundLiteral &bound) +{} +void +Compilation::visit (AST::RangePatternBoundPath &bound) +{} +void +Compilation::visit (AST::RangePatternBoundQualPath &bound) +{} +void +Compilation::visit (AST::RangePattern &pattern) +{} +void +Compilation::visit (AST::ReferencePattern &pattern) +{} +// void Compilation::visit(StructPatternField& field) {} +void +Compilation::visit (AST::StructPatternFieldTuplePat &field) +{} +void +Compilation::visit (AST::StructPatternFieldIdentPat &field) +{} +void +Compilation::visit (AST::StructPatternFieldIdent &field) +{} +void +Compilation::visit (AST::StructPattern &pattern) +{} +// void Compilation::visit(TupleStructItems& tuple_items) {} +void +Compilation::visit (AST::TupleStructItemsNoRange &tuple_items) +{} +void +Compilation::visit (AST::TupleStructItemsRange &tuple_items) +{} +void +Compilation::visit (AST::TupleStructPattern &pattern) +{} +// void Compilation::visit(TuplePatternItems& tuple_items) {} +void +Compilation::visit (AST::TuplePatternItemsMultiple &tuple_items) +{} +void +Compilation::visit (AST::TuplePatternItemsRanged &tuple_items) +{} +void +Compilation::visit (AST::TuplePattern &pattern) +{} +void +Compilation::visit (AST::GroupedPattern &pattern) +{} +void +Compilation::visit (AST::SlicePattern &pattern) +{} + +// rust-stmt.h +void +Compilation::visit (AST::EmptyStmt &stmt) +{} +void + +Compilation::visit (AST::LetStmt &stmt) +{ + printf ("Within LetStmt: %s\n", stmt.as_string ().c_str ()); + + stmt.variables_pattern->accept_vis (*this); + + for (auto it = letPatternBuffer.begin (); it != letPatternBuffer.end (); it++) + { + // scope.Insert (it->first., stmt.type.get ()); + } + + letPatternBuffer.clear (); +} + +void +Compilation::visit (AST::ExprStmtWithoutBlock &stmt) +{} +void +Compilation::visit (AST::ExprStmtWithBlock &stmt) +{} + +// rust-type.h +void +Compilation::visit (AST::TraitBound &bound) +{} +void +Compilation::visit (AST::ImplTraitType &type) +{} +void +Compilation::visit (AST::TraitObjectType &type) +{} +void +Compilation::visit (AST::ParenthesisedType &type) +{} +void +Compilation::visit (AST::ImplTraitTypeOneBound &type) +{} +void +Compilation::visit (AST::TraitObjectTypeOneBound &type) +{} +void +Compilation::visit (AST::TupleType &type) +{} +void +Compilation::visit (AST::NeverType &type) +{} +void +Compilation::visit (AST::RawPointerType &type) +{} +void +Compilation::visit (AST::ReferenceType &type) +{} +void +Compilation::visit (AST::ArrayType &type) +{} +void +Compilation::visit (AST::SliceType &type) +{} +void +Compilation::visit (AST::InferredType &type) +{} +void +Compilation::visit (AST::BareFunctionType &type) +{} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile.h b/gcc/rust/backend/rust-compile.h new file mode 100644 index 0000000..8565847 --- /dev/null +++ b/gcc/rust/backend/rust-compile.h @@ -0,0 +1,246 @@ +#pragma once + +#include "rust-system.h" +#include "rust-ast-full.h" +#include "rust-ast-visitor.h" +#include "rust-backend.h" +#include "scope.h" + +namespace Rust { +namespace Compile { + +class Compilation : public AST::ASTVisitor +{ +public: + static bool Compile (AST::Crate &crate, ::Backend *backend); + + ~Compilation (); + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (AST::Token &tok); + virtual void visit (AST::DelimTokenTree &delim_tok_tree); + virtual void visit (AST::AttrInputMetaItemContainer &input); + // virtual void visit(MetaItem& meta_item); + // virtual void vsit(Stmt& stmt); + // virtual void visit(Expr& expr); + virtual void visit (AST::IdentifierExpr &ident_expr); + // virtual void visit(Pattern& pattern); + // virtual void visit(Type& type); + // virtual void visit(TypeParamBound& type_param_bound); + virtual void visit (AST::Lifetime &lifetime); + // virtual void visit(GenericParam& generic_param); + virtual void visit (AST::LifetimeParam &lifetime_param); + // virtual void visit(TraitItem& trait_item); + // virtual void visit(InherentImplItem& inherent_impl_item); + // virtual void visit(TraitImplItem& trait_impl_item); + virtual void visit (AST::MacroInvocationSemi ¯o); + + // rust-path.h + virtual void visit (AST::PathInExpression &path); + virtual void visit (AST::TypePathSegment &segment); + virtual void visit (AST::TypePathSegmentGeneric &segment); + virtual void visit (AST::TypePathSegmentFunction &segment); + virtual void visit (AST::TypePath &path); + virtual void visit (AST::QualifiedPathInExpression &path); + virtual void visit (AST::QualifiedPathInType &path); + + // rust-expr.h + virtual void visit (AST::LiteralExpr &expr); + virtual void visit (AST::AttrInputLiteral &attr_input); + virtual void visit (AST::MetaItemLitExpr &meta_item); + virtual void visit (AST::MetaItemPathLit &meta_item); + virtual void visit (AST::BorrowExpr &expr); + virtual void visit (AST::DereferenceExpr &expr); + virtual void visit (AST::ErrorPropagationExpr &expr); + virtual void visit (AST::NegationExpr &expr); + virtual void visit (AST::ArithmeticOrLogicalExpr &expr); + virtual void visit (AST::ComparisonExpr &expr); + virtual void visit (AST::LazyBooleanExpr &expr); + virtual void visit (AST::TypeCastExpr &expr); + virtual void visit (AST::AssignmentExpr &expr); + virtual void visit (AST::CompoundAssignmentExpr &expr); + virtual void visit (AST::GroupedExpr &expr); + // virtual void visit(ArrayElems& elems); + virtual void visit (AST::ArrayElemsValues &elems); + virtual void visit (AST::ArrayElemsCopied &elems); + virtual void visit (AST::ArrayExpr &expr); + virtual void visit (AST::ArrayIndexExpr &expr); + virtual void visit (AST::TupleExpr &expr); + virtual void visit (AST::TupleIndexExpr &expr); + virtual void visit (AST::StructExprStruct &expr); + // virtual void visit(StructExprField& field); + virtual void visit (AST::StructExprFieldIdentifier &field); + virtual void visit (AST::StructExprFieldIdentifierValue &field); + virtual void visit (AST::StructExprFieldIndexValue &field); + virtual void visit (AST::StructExprStructFields &expr); + virtual void visit (AST::StructExprStructBase &expr); + virtual void visit (AST::StructExprTuple &expr); + virtual void visit (AST::StructExprUnit &expr); + // virtual void visit(EnumExprField& field); + virtual void visit (AST::EnumExprFieldIdentifier &field); + virtual void visit (AST::EnumExprFieldIdentifierValue &field); + virtual void visit (AST::EnumExprFieldIndexValue &field); + virtual void visit (AST::EnumExprStruct &expr); + virtual void visit (AST::EnumExprTuple &expr); + virtual void visit (AST::EnumExprFieldless &expr); + virtual void visit (AST::CallExpr &expr); + virtual void visit (AST::MethodCallExpr &expr); + virtual void visit (AST::FieldAccessExpr &expr); + virtual void visit (AST::ClosureExprInner &expr); + virtual void visit (AST::BlockExpr &expr); + virtual void visit (AST::ClosureExprInnerTyped &expr); + virtual void visit (AST::ContinueExpr &expr); + virtual void visit (AST::BreakExpr &expr); + virtual void visit (AST::RangeFromToExpr &expr); + virtual void visit (AST::RangeFromExpr &expr); + virtual void visit (AST::RangeToExpr &expr); + virtual void visit (AST::RangeFullExpr &expr); + virtual void visit (AST::RangeFromToInclExpr &expr); + virtual void visit (AST::RangeToInclExpr &expr); + virtual void visit (AST::ReturnExpr &expr); + virtual void visit (AST::UnsafeBlockExpr &expr); + virtual void visit (AST::LoopExpr &expr); + virtual void visit (AST::WhileLoopExpr &expr); + virtual void visit (AST::WhileLetLoopExpr &expr); + virtual void visit (AST::ForLoopExpr &expr); + virtual void visit (AST::IfExpr &expr); + virtual void visit (AST::IfExprConseqElse &expr); + virtual void visit (AST::IfExprConseqIf &expr); + virtual void visit (AST::IfExprConseqIfLet &expr); + virtual void visit (AST::IfLetExpr &expr); + virtual void visit (AST::IfLetExprConseqElse &expr); + virtual void visit (AST::IfLetExprConseqIf &expr); + virtual void visit (AST::IfLetExprConseqIfLet &expr); + // virtual void visit(MatchCase& match_case); + virtual void visit (AST::MatchCaseBlockExpr &match_case); + virtual void visit (AST::MatchCaseExpr &match_case); + virtual void visit (AST::MatchExpr &expr); + virtual void visit (AST::AwaitExpr &expr); + virtual void visit (AST::AsyncBlockExpr &expr); + + // rust-item.h + virtual void visit (AST::TypeParam ¶m); + // virtual void visit(WhereClauseItem& item); + virtual void visit (AST::LifetimeWhereClauseItem &item); + virtual void visit (AST::TypeBoundWhereClauseItem &item); + virtual void visit (AST::Method &method); + virtual void visit (AST::ModuleBodied &module); + virtual void visit (AST::ModuleNoBody &module); + virtual void visit (AST::ExternCrate &crate); + // virtual void visit(UseTree& use_tree); + virtual void visit (AST::UseTreeGlob &use_tree); + virtual void visit (AST::UseTreeList &use_tree); + virtual void visit (AST::UseTreeRebind &use_tree); + virtual void visit (AST::UseDeclaration &use_decl); + virtual void visit (AST::Function &function); + virtual void visit (AST::TypeAlias &type_alias); + virtual void visit (AST::StructStruct &struct_item); + virtual void visit (AST::TupleStruct &tuple_struct); + virtual void visit (AST::EnumItem &item); + virtual void visit (AST::EnumItemTuple &item); + virtual void visit (AST::EnumItemStruct &item); + virtual void visit (AST::EnumItemDiscriminant &item); + virtual void visit (AST::Enum &enum_item); + virtual void visit (AST::Union &union_item); + virtual void visit (AST::ConstantItem &const_item); + virtual void visit (AST::StaticItem &static_item); + virtual void visit (AST::TraitItemFunc &item); + virtual void visit (AST::TraitItemMethod &item); + virtual void visit (AST::TraitItemConst &item); + virtual void visit (AST::TraitItemType &item); + virtual void visit (AST::Trait &trait); + virtual void visit (AST::InherentImpl &impl); + virtual void visit (AST::TraitImpl &impl); + // virtual void visit(ExternalItem& item); + virtual void visit (AST::ExternalStaticItem &item); + virtual void visit (AST::ExternalFunctionItem &item); + virtual void visit (AST::ExternBlock &block); + + // rust-macro.h + virtual void visit (AST::MacroMatchFragment &match); + virtual void visit (AST::MacroMatchRepetition &match); + virtual void visit (AST::MacroMatcher &matcher); + virtual void visit (AST::MacroRulesDefinition &rules_def); + virtual void visit (AST::MacroInvocation ¯o_invoc); + virtual void visit (AST::MetaItemPath &meta_item); + virtual void visit (AST::MetaItemSeq &meta_item); + virtual void visit (AST::MetaWord &meta_item); + virtual void visit (AST::MetaNameValueStr &meta_item); + virtual void visit (AST::MetaListPaths &meta_item); + virtual void visit (AST::MetaListNameValueStr &meta_item); + + // rust-pattern.h + virtual void visit (AST::LiteralPattern &pattern); + virtual void visit (AST::IdentifierPattern &pattern); + virtual void visit (AST::WildcardPattern &pattern); + // virtual void visit(RangePatternBound& bound); + virtual void visit (AST::RangePatternBoundLiteral &bound); + virtual void visit (AST::RangePatternBoundPath &bound); + virtual void visit (AST::RangePatternBoundQualPath &bound); + virtual void visit (AST::RangePattern &pattern); + virtual void visit (AST::ReferencePattern &pattern); + // virtual void visit(StructPatternField& field); + virtual void visit (AST::StructPatternFieldTuplePat &field); + virtual void visit (AST::StructPatternFieldIdentPat &field); + virtual void visit (AST::StructPatternFieldIdent &field); + virtual void visit (AST::StructPattern &pattern); + // virtual void visit(TupleStructItems& tuple_items); + virtual void visit (AST::TupleStructItemsNoRange &tuple_items); + virtual void visit (AST::TupleStructItemsRange &tuple_items); + virtual void visit (AST::TupleStructPattern &pattern); + // virtual void visit(TuplePatternItems& tuple_items); + virtual void visit (AST::TuplePatternItemsMultiple &tuple_items); + virtual void visit (AST::TuplePatternItemsRanged &tuple_items); + virtual void visit (AST::TuplePattern &pattern); + virtual void visit (AST::GroupedPattern &pattern); + virtual void visit (AST::SlicePattern &pattern); + + // rust-stmt.h + virtual void visit (AST::EmptyStmt &stmt); + virtual void visit (AST::LetStmt &stmt); + virtual void visit (AST::ExprStmtWithoutBlock &stmt); + virtual void visit (AST::ExprStmtWithBlock &stmt); + + // rust-type.h + virtual void visit (AST::TraitBound &bound); + virtual void visit (AST::ImplTraitType &type); + virtual void visit (AST::TraitObjectType &type); + virtual void visit (AST::ParenthesisedType &type); + virtual void visit (AST::ImplTraitTypeOneBound &type); + virtual void visit (AST::TraitObjectTypeOneBound &type); + virtual void visit (AST::TupleType &type); + virtual void visit (AST::NeverType &type); + virtual void visit (AST::RawPointerType &type); + virtual void visit (AST::ReferenceType &type); + virtual void visit (AST::ArrayType &type); + virtual void visit (AST::SliceType &type); + virtual void visit (AST::InferredType &type); + virtual void visit (AST::BareFunctionType &type); + +private: + Compilation (AST::Crate &crate, Backend *backend); + + bool go (); + + Analysis::Scope scope; + AST::Crate &crate; + Backend *backend; + + /* we need lots of members to be buffers for translation of the AST */ + std::vector letPatternBuffer; + + ::Bfunction *currentFndecl; + ::Btype *translatedType; + + std::vector< ::Btype *> type_decls; + std::vector< ::Bvariable *> var_decls; + std::vector< ::Bexpression *> const_decls; + std::vector< ::Bfunction *> func_decls; +}; + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h new file mode 100644 index 0000000..ccc5e47 --- /dev/null +++ b/gcc/rust/rust-backend.h @@ -0,0 +1,761 @@ +#pragma once + +#include +#include +#include + +#include "operator.h" + +extern bool +saw_errors (void); + +// TODO: Will have to be significantly modified to work with Rust and current +// setup of gccrs + +// Pointers to these types are created by the backend, passed to the +// frontend, and passed back to the backend. The types must be +// defined by the backend using these names. + +// The backend representation of a type. +class Btype; + +// The backend represention of an expression. +class Bexpression; + +// The backend representation of a statement. +class Bstatement; + +// The backend representation of a function definition or declaration. +class Bfunction; + +// The backend representation of a block. +class Bblock; + +// The backend representation of a variable. +class Bvariable; + +// The backend representation of a label. +class Blabel; + +// The backend interface. This is a pure abstract class that a +// specific backend will implement. + +class Backend +{ +public: + virtual ~Backend () {} + + // Name/type/location. Used for function parameters, struct fields, + // interface methods. + struct Btyped_identifier + { + std::string name; + Btype *btype; + Location location; + + Btyped_identifier () + : name (), btype (NULL), location (Linemap::unknown_location ()) + {} + + Btyped_identifier (const std::string &a_name, Btype *a_btype, + Location a_location) + : name (a_name), btype (a_btype), location (a_location) + {} + }; + + // Types. + + // Produce an error type. Actually the backend could probably just + // crash if this is called. + virtual Btype *error_type () = 0; + + // Get a void type. This is used in (at least) two ways: 1) as the + // return type of a function with no result parameters; 2) + // unsafe.Pointer is represented as *void. + virtual Btype *void_type () = 0; + + // Get the unnamed boolean type. + virtual Btype *bool_type () = 0; + + // Get an unnamed integer type with the given signedness and number + // of bits. + virtual Btype *integer_type (bool is_unsigned, int bits) = 0; + + // Get an unnamed floating point type with the given number of bits + // (32 or 64). + virtual Btype *float_type (int bits) = 0; + + // Get an unnamed complex type with the given number of bits (64 or 128). + virtual Btype *complex_type (int bits) = 0; + + // Get a pointer type. + virtual Btype *pointer_type (Btype *to_type) = 0; + + // Get a function type. The receiver, parameter, and results are + // generated from the types in the Function_type. The Function_type + // is provided so that the names are available. This should return + // not the type of a Go function (which is a pointer to a struct) + // but the type of a C function pointer (which will be used as the + // type of the first field of the struct). If there is more than + // one result, RESULT_STRUCT is a struct type to hold the results, + // and RESULTS may be ignored; if there are zero or one results, + // RESULT_STRUCT is NULL. + virtual Btype * + function_type (const Btyped_identifier &receiver, + const std::vector ¶meters, + const std::vector &results, + Btype *result_struct, Location location) + = 0; + + // Get a struct type. + virtual Btype *struct_type (const std::vector &fields) = 0; + + // Get an array type. + virtual Btype *array_type (Btype *element_type, Bexpression *length) = 0; + + // Create a placeholder pointer type. This is used for a named + // pointer type, since in Go a pointer type may refer to itself. + // NAME is the name of the type, and the location is where the named + // type is defined. This function is also used for unnamed function + // types with multiple results, in which case the type has no name + // and NAME will be empty. FOR_FUNCTION is true if this is for a C + // pointer to function type. A Go func type is represented as a + // pointer to a struct, and the first field of the struct is a C + // pointer to function. The return value will later be passed as + // the first parameter to set_placeholder_pointer_type or + // set_placeholder_function_type. + virtual Btype *placeholder_pointer_type (const std::string &name, Location, + bool for_function) + = 0; + + // Fill in a placeholder pointer type as a pointer. This takes a + // type returned by placeholder_pointer_type and arranges for it to + // point to the type that TO_TYPE points to (that is, PLACEHOLDER + // becomes the same type as TO_TYPE). Returns true on success, + // false on failure. + virtual bool set_placeholder_pointer_type (Btype *placeholder, Btype *to_type) + = 0; + + // Fill in a placeholder pointer type as a function. This takes a + // type returned by placeholder_pointer_type and arranges for it to + // become a real Go function type (which corresponds to a C/C++ + // pointer to function type). FT will be something returned by the + // function_type method. Returns true on success, false on failure. + virtual bool set_placeholder_function_type (Btype *placeholder, Btype *ft) + = 0; + + // Create a placeholder struct type. This is used for a named + // struct type, as with placeholder_pointer_type. It is also used + // for interface types, in which case NAME will be the empty string. + virtual Btype *placeholder_struct_type (const std::string &name, Location) + = 0; + + // Fill in a placeholder struct type. This takes a type returned by + // placeholder_struct_type and arranges for it to become a real + // struct type. The parameter is as for struct_type. Returns true + // on success, false on failure. + virtual bool + set_placeholder_struct_type (Btype *placeholder, + const std::vector &fields) + = 0; + + // Create a placeholder array type. This is used for a named array + // type, as with placeholder_pointer_type, to handle cases like + // type A []*A. + virtual Btype *placeholder_array_type (const std::string &name, Location) = 0; + + // Fill in a placeholder array type. This takes a type returned by + // placeholder_array_type and arranges for it to become a real array + // type. The parameters are as for array_type. Returns true on + // success, false on failure. + virtual bool set_placeholder_array_type (Btype *placeholder, + Btype *element_type, + Bexpression *length) + = 0; + + // Return a named version of a type. The location is the location + // of the type definition. This will not be called for a type + // created via placeholder_pointer_type, placeholder_struct_type, or + // placeholder_array_type.. (It may be called for a pointer, + // struct, or array type in a case like "type P *byte; type Q P".) + virtual Btype *named_type (const std::string &name, Btype *, Location) = 0; + + // Create a marker for a circular pointer type. Go pointer and + // function types can refer to themselves in ways that are not + // permitted in C/C++. When a circular type is found, this function + // is called for the circular reference. This permits the backend + // to decide how to handle such a type. PLACEHOLDER is the + // placeholder type which has already been created; if the backend + // is prepared to handle a circular pointer type, it may simply + // return PLACEHOLDER. FOR_FUNCTION is true if this is for a + // function type. + // + // For "type P *P" the sequence of calls will be + // bt1 = placeholder_pointer_type(); + // bt2 = circular_pointer_type(bt1, false); + // set_placeholder_pointer_type(bt1, bt2); + virtual Btype *circular_pointer_type (Btype *placeholder, bool for_function) + = 0; + + // Return whether the argument could be a special type created by + // circular_pointer_type. This is used to introduce explicit type + // conversions where needed. If circular_pointer_type returns its + // PLACEHOLDER parameter, this may safely always return false. + virtual bool is_circular_pointer_type (Btype *) = 0; + + // Return the size of a type. + virtual int64_t type_size (Btype *) = 0; + + // Return the alignment of a type. + virtual int64_t type_alignment (Btype *) = 0; + + // Return the alignment of a struct field of this type. This is + // normally the same as type_alignment, but not always. + virtual int64_t type_field_alignment (Btype *) = 0; + + // Return the offset of field INDEX in a struct type. INDEX is the + // entry in the FIELDS std::vector parameter of struct_type or + // set_placeholder_struct_type. + virtual int64_t type_field_offset (Btype *, size_t index) = 0; + + // Expressions. + + // Return an expression for a zero value of the given type. This is + // used for cases such as local variable initialization and + // converting nil to other types. + virtual Bexpression *zero_expression (Btype *) = 0; + + // Create an error expression. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // going without crashing. + virtual Bexpression *error_expression () = 0; + + // Create a nil pointer expression. + virtual Bexpression *nil_pointer_expression () = 0; + + // Create a reference to a variable. + virtual Bexpression *var_expression (Bvariable *var, Location) = 0; + + // Create an expression that indirects through the pointer expression EXPR + // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer + // is known to point to a valid memory location. BTYPE is the expected type + // of the indirected EXPR. + virtual Bexpression *indirect_expression (Btype *btype, Bexpression *expr, + bool known_valid, Location) + = 0; + + // Return an expression that declares a constant named NAME with the + // constant value VAL in BTYPE. + virtual Bexpression *named_constant_expression (Btype *btype, + const std::string &name, + Bexpression *val, Location) + = 0; + + // Return an expression for the multi-precision integer VAL in BTYPE. + virtual Bexpression *integer_constant_expression (Btype *btype, mpz_t val) + = 0; + + // Return an expression for the floating point value VAL in BTYPE. + virtual Bexpression *float_constant_expression (Btype *btype, mpfr_t val) = 0; + + // Return an expression for the complex value VAL in BTYPE. + virtual Bexpression *complex_constant_expression (Btype *btype, mpc_t val) + = 0; + + // Return an expression for the string value VAL. + virtual Bexpression *string_constant_expression (const std::string &val) = 0; + + // Return an expression for the boolean value VAL. + virtual Bexpression *boolean_constant_expression (bool val) = 0; + + // Return an expression for the real part of BCOMPLEX. + virtual Bexpression *real_part_expression (Bexpression *bcomplex, Location) + = 0; + + // Return an expression for the imaginary part of BCOMPLEX. + virtual Bexpression *imag_part_expression (Bexpression *bcomplex, Location) + = 0; + + // Return an expression for the complex number (BREAL, BIMAG). + virtual Bexpression *complex_expression (Bexpression *breal, + Bexpression *bimag, Location) + = 0; + + // Return an expression that converts EXPR to TYPE. + virtual Bexpression *convert_expression (Btype *type, Bexpression *expr, + Location) + = 0; + + // Create an expression for the address of a function. This is used to + // get the address of the code for a function. + virtual Bexpression *function_code_expression (Bfunction *, Location) = 0; + + // Create an expression that takes the address of an expression. + virtual Bexpression *address_expression (Bexpression *, Location) = 0; + + // Return an expression for the field at INDEX in BSTRUCT. + virtual Bexpression *struct_field_expression (Bexpression *bstruct, + size_t index, Location) + = 0; + + // Create an expression that executes BSTAT before BEXPR. + virtual Bexpression *compound_expression (Bstatement *bstat, + Bexpression *bexpr, Location) + = 0; + + // Return an expression that executes THEN_EXPR if CONDITION is true, or + // ELSE_EXPR otherwise and returns the result as type BTYPE, within the + // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. + virtual Bexpression * + conditional_expression (Bfunction *function, Btype *btype, + Bexpression *condition, Bexpression *then_expr, + Bexpression *else_expr, Location) + = 0; + + // Return an expression for the unary operation OP EXPR. + // Supported values of OP are (from operators.h): + // MINUS, NOT, XOR. + virtual Bexpression *unary_expression (Operator op, Bexpression *expr, + Location) + = 0; + + // Return an expression for the binary operation LEFT OP RIGHT. + // Supported values of OP are (from operators.h): + // EQEQ, NOTEQ, LT, LE, GT, GE, PLUS, MINUS, OR, XOR, MULT, DIV, MOD, + // LSHIFT, RSHIFT, AND, NOT. + virtual Bexpression *binary_expression (Operator op, Bexpression *left, + Bexpression *right, Location) + = 0; + + // Return an expression that constructs BTYPE with VALS. BTYPE must be the + // backend representation a of struct. VALS must be in the same order as the + // corresponding fields in BTYPE. + virtual Bexpression * + constructor_expression (Btype *btype, const std::vector &vals, + Location) + = 0; + + // Return an expression that constructs an array of BTYPE with INDEXES and + // VALS. INDEXES and VALS must have the same amount of elements. Each index + // in INDEXES must be in the same order as the corresponding value in VALS. + virtual Bexpression *array_constructor_expression ( + Btype *btype, const std::vector &indexes, + const std::vector &vals, Location) + = 0; + + // Return an expression for the address of BASE[INDEX]. + // BASE has a pointer type. This is used for slice indexing. + virtual Bexpression *pointer_offset_expression (Bexpression *base, + Bexpression *index, Location) + = 0; + + // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid + // fixed-length array, not a slice. + virtual Bexpression *array_index_expression (Bexpression *array, + Bexpression *index, Location) + = 0; + + // Create an expression for a call to FN with ARGS, taking place within + // caller CALLER. + virtual Bexpression *call_expression (Bfunction *caller, Bexpression *fn, + const std::vector &args, + Bexpression *static_chain, Location) + = 0; + + // Statements. + + // Create an error statement. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // going without crashing. + virtual Bstatement *error_statement () = 0; + + // Create an expression statement within the specified function. + virtual Bstatement *expression_statement (Bfunction *, Bexpression *) = 0; + + // Create a variable initialization statement in the specified + // function. This initializes a local variable at the point in the + // program flow where it is declared. + virtual Bstatement *init_statement (Bfunction *, Bvariable *var, + Bexpression *init) + = 0; + + // Create an assignment statement within the specified function. + virtual Bstatement *assignment_statement (Bfunction *, Bexpression *lhs, + Bexpression *rhs, Location) + = 0; + + // Create a return statement, passing the representation of the + // function and the list of values to return. + virtual Bstatement * + return_statement (Bfunction *, const std::vector &, Location) + = 0; + + // Create an if statement within a function. ELSE_BLOCK may be NULL. + virtual Bstatement *if_statement (Bfunction *, Bexpression *condition, + Bblock *then_block, Bblock *else_block, + Location) + = 0; + + // Create a switch statement where the case values are constants. + // CASES and STATEMENTS must have the same number of entries. If + // VALUE matches any of the list in CASES[i], which will all be + // integers, then STATEMENTS[i] is executed. STATEMENTS[i] will + // either end with a goto statement or will fall through into + // STATEMENTS[i + 1]. CASES[i] is empty for the default clause, + // which need not be last. FUNCTION is the current function. + virtual Bstatement * + switch_statement (Bfunction *function, Bexpression *value, + const std::vector > &cases, + const std::vector &statements, Location) + = 0; + + // Create a single statement from two statements. + virtual Bstatement *compound_statement (Bstatement *, Bstatement *) = 0; + + // Create a single statement from a list of statements. + virtual Bstatement *statement_list (const std::vector &) = 0; + + // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if + // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and + // if not NULL, it will always be executed. This is used for handling defers + // in Go functions. In C++, the resulting code is of this form: + // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } + virtual Bstatement * + exception_handler_statement (Bstatement *bstat, Bstatement *except_stmt, + Bstatement *finally_stmt, Location) + = 0; + + // Blocks. + + // Create a block. The frontend will call this function when it + // starts converting a block within a function. FUNCTION is the + // current function. ENCLOSING is the enclosing block; it will be + // NULL for the top-level block in a function. VARS is the list of + // local variables defined within this block; each entry will be + // created by the local_variable function. START_LOCATION is the + // location of the start of the block, more or less the location of + // the initial curly brace. END_LOCATION is the location of the end + // of the block, more or less the location of the final curly brace. + // The statements will be added after the block is created. + virtual Bblock *block (Bfunction *function, Bblock *enclosing, + const std::vector &vars, + Location start_location, Location end_location) + = 0; + + // Add the statements to a block. The block is created first. Then + // the statements are created. Then the statements are added to the + // block. This will called exactly once per block. The vector may + // be empty if there are no statements. + virtual void block_add_statements (Bblock *, + const std::vector &) + = 0; + + // Return the block as a statement. This is used to include a block + // in a list of statements. + virtual Bstatement *block_statement (Bblock *) = 0; + + // Variables. + + // Create an error variable. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // going without crashing. + virtual Bvariable *error_variable () = 0; + + // Create a global variable. NAME is the package-qualified name of + // the variable. ASM_NAME is the encoded identifier for the + // variable, incorporating the package, and made safe for the + // assembler. BTYPE is the type of the variable. IS_EXTERNAL is + // true if the variable is defined in some other package. IS_HIDDEN + // is true if the variable is not exported (name begins with a lower + // case letter). IN_UNIQUE_SECTION is true if the variable should + // be put into a unique section if possible; this is intended to + // permit the linker to garbage collect the variable if it is not + // referenced. LOCATION is where the variable was defined. + virtual Bvariable *global_variable (const std::string &name, + const std::string &asm_name, Btype *btype, + bool is_external, bool is_hidden, + bool in_unique_section, Location location) + = 0; + + // A global variable will 1) be initialized to zero, or 2) be + // initialized to a constant value, or 3) be initialized in the init + // function. In case 2, the frontend will call + // global_variable_set_init to set the initial value. If this is + // not called, the backend should initialize a global variable to 0. + // The init function may then assign a value to it. + virtual void global_variable_set_init (Bvariable *, Bexpression *) = 0; + + // Create a local variable. The frontend will create the local + // variables first, and then create the block which contains them. + // FUNCTION is the function in which the variable is defined. NAME + // is the name of the variable. TYPE is the type. DECL_VAR, if not + // null, gives the location at which the value of this variable may + // be found, typically used to create an inner-scope reference to an + // outer-scope variable, to extend the lifetime of the variable beyond + // the inner scope. IS_ADDRESS_TAKEN is true if the address of this + // variable is taken (this implies that the address does not escape + // the function, as otherwise the variable would be on the heap). + // LOCATION is where the variable is defined. For each local variable + // the frontend will call init_statement to set the initial value. + virtual Bvariable * + local_variable (Bfunction *function, const std::string &name, Btype *type, + Bvariable *decl_var, bool is_address_taken, Location location) + = 0; + + // Create a function parameter. This is an incoming parameter, not + // a result parameter (result parameters are treated as local + // variables). The arguments are as for local_variable. + virtual Bvariable * + parameter_variable (Bfunction *function, const std::string &name, Btype *type, + bool is_address_taken, Location location) + = 0; + + // Create a static chain parameter. This is the closure parameter. + virtual Bvariable *static_chain_variable (Bfunction *function, + const std::string &name, + Btype *type, Location location) + = 0; + + // Create a temporary variable. A temporary variable has no name, + // just a type. We pass in FUNCTION and BLOCK in case they are + // needed. If INIT is not NULL, the variable should be initialized + // to that value. Otherwise the initial value is irrelevant--the + // backend does not have to explicitly initialize it to zero. + // ADDRESS_IS_TAKEN is true if the programs needs to take the + // address of this temporary variable. LOCATION is the location of + // the statement or expression which requires creating the temporary + // variable, and may not be very useful. This function should + // return a variable which can be referenced later and should set + // *PSTATEMENT to a statement which initializes the variable. + virtual Bvariable * + temporary_variable (Bfunction *, Bblock *, Btype *, Bexpression *init, + bool address_is_taken, Location location, + Bstatement **pstatement) + = 0; + + // Create an implicit variable that is compiler-defined. This is + // used when generating GC data and roots, when storing the values + // of a slice constructor, and for the zero value of types. This returns a + // Bvariable because it corresponds to an initialized variable in C. + // + // NAME is the name to use for the initialized variable this will create. + // + // ASM_NAME is encoded assembler-friendly version of the name, or the + // empty string if no encoding is needed. + // + // TYPE is the type of the implicit variable. + // + // IS_HIDDEN will be true if the descriptor should only be visible + // within the current object. + // + // IS_CONSTANT is true if the implicit variable should be treated like it is + // immutable. For slice initializers, if the values must be copied to the + // heap, the variable IS_CONSTANT. + // + // IS_COMMON is true if the implicit variable should + // be treated as a common variable (multiple definitions with + // different sizes permitted in different object files, all merged + // into the largest definition at link time); this will be true for + // the zero value. IS_HIDDEN and IS_COMMON will never both be true. + // + // If ALIGNMENT is not zero, it is the desired alignment of the variable. + virtual Bvariable * + implicit_variable (const std::string &name, const std::string &asm_name, + Btype *type, bool is_hidden, bool is_constant, + bool is_common, int64_t alignment) + = 0; + + // Set the initial value of a variable created by implicit_variable. + // This must be called even if there is no initializer, i.e., INIT is NULL. + // The NAME, TYPE, IS_HIDDEN, IS_CONSTANT, and IS_COMMON parameters are + // the same ones passed to implicit_variable. INIT will be a composite + // literal of type TYPE. It will not contain any function calls or anything + // else that can not be put into a read-only data section. + // It may contain the address of variables created by implicit_variable. + // + // If IS_COMMON is true, INIT will be NULL, and the + // variable should be initialized to all zeros. + virtual void implicit_variable_set_init (Bvariable *, const std::string &name, + Btype *type, bool is_hidden, + bool is_constant, bool is_common, + Bexpression *init) + = 0; + + // Create a reference to a named implicit variable defined in some + // other package. This will be a variable created by a call to + // implicit_variable with the same NAME, ASM_NAME and TYPE and with + // IS_COMMON passed as false. This corresponds to an extern global + // variable in C. + virtual Bvariable *implicit_variable_reference (const std::string &name, + const std::string &asm_name, + Btype *type) + = 0; + + // Create a named immutable initialized data structure. This is + // used for type descriptors, map descriptors, and function + // descriptors. This returns a Bvariable because it corresponds to + // an initialized const variable in C. + // + // NAME is the name to use for the initialized global variable which + // this call will create. + // + // ASM_NAME is the encoded, assembler-friendly version of NAME, or + // the empty string if no encoding is needed. + // + // IS_HIDDEN will be true if the descriptor should only be visible + // within the current object. + // + // IS_COMMON is true if NAME may be defined by several packages, and + // the linker should merge all such definitions. If IS_COMMON is + // false, NAME should be defined in only one file. In general + // IS_COMMON will be true for the type descriptor of an unnamed type + // or a builtin type. IS_HIDDEN and IS_COMMON will never both be + // true. + // + // TYPE will be a struct type; the type of the returned expression + // must be a pointer to this struct type. + // + // We must create the named structure before we know its + // initializer, because the initializer may refer to its own + // address. After calling this the frontend will call + // immutable_struct_set_init. + virtual Bvariable * + immutable_struct (const std::string &name, const std::string &asm_name, + bool is_hidden, bool is_common, Btype *type, Location) + = 0; + + // Set the initial value of a variable created by immutable_struct. + // The NAME, IS_HIDDEN, IS_COMMON, TYPE, and location parameters are + // the same ones passed to immutable_struct. INITIALIZER will be a + // composite literal of type TYPE. It will not contain any function + // calls or anything else that can not be put into a read-only data + // section. It may contain the address of variables created by + // immutable_struct. + virtual void immutable_struct_set_init (Bvariable *, const std::string &name, + bool is_hidden, bool is_common, + Btype *type, Location, + Bexpression *initializer) + = 0; + + // Create a reference to a named immutable initialized data + // structure defined in some other package. This will be a + // structure created by a call to immutable_struct with the same + // NAME, ASM_NAME and TYPE and with IS_COMMON passed as false. This + // corresponds to an extern const global variable in C. + virtual Bvariable *immutable_struct_reference (const std::string &name, + const std::string &asm_name, + Btype *type, Location) + = 0; + + // Labels. + + // Create a new label. NAME will be empty if this is a label + // created by the frontend for a loop construct. The location is + // where the label is defined. + virtual Blabel *label (Bfunction *, const std::string &name, Location) = 0; + + // Create a statement which defines a label. This statement will be + // put into the codestream at the point where the label should be + // defined. + virtual Bstatement *label_definition_statement (Blabel *) = 0; + + // Create a goto statement to a label. + virtual Bstatement *goto_statement (Blabel *, Location) = 0; + + // Create an expression for the address of a label. This is used to + // get the return address of a deferred function which may call + // recover. + virtual Bexpression *label_address (Blabel *, Location) = 0; + + // Functions. + + // Create an error function. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // going without crashing. + virtual Bfunction *error_function () = 0; + + // Bit flags to pass to the function method. + + // Set if the function should be visible outside of the current + // compilation unit. + static const unsigned int function_is_visible = 1 << 0; + + // Set if this is a function declaration rather than a definition; + // the definition will be in another compilation unit. + static const unsigned int function_is_declaration = 1 << 1; + + // Set if the function can be inlined. This is normally set, but is + // false for functions that may not be inlined because they call + // recover and must be visible for correct panic recovery. + static const unsigned int function_is_inlinable = 1 << 2; + + // Set if the function may not split the stack. This is set for the + // implementation of recover itself, among other things. + static const unsigned int function_no_split_stack = 1 << 3; + + // Set if the function does not return. This is set for the + // implementation of panic. + static const unsigned int function_does_not_return = 1 << 4; + + // Set if the function should be put in a unique section if + // possible. This is used for field tracking. + static const unsigned int function_in_unique_section = 1 << 5; + + // Set if the function should be available for inlining in the + // backend, but should not be emitted as a standalone function. Any + // call to the function that is not inlined should be treated as a + // call to a function defined in a different compilation unit. This + // is like a C99 function marked inline but not extern. + static const unsigned int function_only_inline = 1 << 6; + + // Declare or define a function of FNTYPE. + // NAME is the Go name of the function. ASM_NAME, if not the empty + // string, is the name that should be used in the symbol table; this + // will be non-empty if a magic extern comment is used. FLAGS is + // bit flags described above. + virtual Bfunction *function (Btype *fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, + Location) + = 0; + + // Create a statement that runs all deferred calls for FUNCTION. This should + // be a statement that looks like this in C++: + // finish: + // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } + virtual Bstatement * + function_defer_statement (Bfunction *function, Bexpression *undefer, + Bexpression *check_defer, Location) + = 0; + + // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. + // This will only be called for a function definition. Returns true on + // success, false on failure. + virtual bool + function_set_parameters (Bfunction *function, + const std::vector ¶m_vars) + = 0; + + // Set the function body for FUNCTION using the code in CODE_STMT. Returns + // true on success, false on failure. + virtual bool function_set_body (Bfunction *function, Bstatement *code_stmt) + = 0; + + // Look up a named built-in function in the current backend implementation. + // Returns NULL if no built-in function by that name exists. + virtual Bfunction *lookup_builtin (const std::string &) = 0; + + // Utility. + + // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, + // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. + virtual void + write_global_definitions (const std::vector &type_decls, + const std::vector &constant_decls, + const std::vector &function_decls, + const std::vector &variable_decls) + = 0; + + // Write SIZE bytes of export data from BYTES to the proper + // section in the output object file. + virtual void write_export_data (const char *bytes, unsigned int size) = 0; +}; diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 6699b47..474986d 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -46,7 +46,7 @@ #include "rust-location.h" #include "rust-linemap.h" -#include "backend.h" +#include "rust-backend.h" #include "rust-object-export.h" // TODO: this will have to be significantly modified to work with Rust @@ -428,7 +428,6 @@ private: tree convert_tree (tree, tree, Location); private: -<<<<<<< HEAD static const int builtin_const = 1 << 0; static const int builtin_noreturn = 1 << 1; static const int builtin_novops = 1 << 2; @@ -437,13 +436,6 @@ private: const char *libname, tree fntype, int flags); // A mapping of the GCC built-ins exposed to GCCRust. -======= - void define_builtin (built_in_function bcode, const char *name, - const char *libname, tree fntype, bool const_p, - bool noreturn_p); - - // A mapping of the GCC built-ins exposed to GCCGo. ->>>>>>> 12e994a7967... Fix indentation std::map builtin_functions_; }; @@ -464,42 +456,22 @@ Gcc_backend::Gcc_backend () tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree (); tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", -<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); -======= - NULL, build_function_type_list (t, p, t, NULL_TREE), - false, false); ->>>>>>> 12e994a7967... Fix indentation t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree (); p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", -<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); -======= - NULL, build_function_type_list (t, p, t, NULL_TREE), - false, false); ->>>>>>> 12e994a7967... Fix indentation t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree (); p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", -<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); -======= - NULL, build_function_type_list (t, p, t, NULL_TREE), - false, false); ->>>>>>> 12e994a7967... Fix indentation t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree (); p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", -<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); -======= - NULL, build_function_type_list (t, p, t, NULL_TREE), - false, false); ->>>>>>> 12e994a7967... Fix indentation // We use __builtin_expect for magic import functions. this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL, @@ -507,11 +479,7 @@ Gcc_backend::Gcc_backend () long_integer_type_node, long_integer_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); -======= - true, false); ->>>>>>> 12e994a7967... Fix indentation // We use __builtin_memcmp for struct comparisons. this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", @@ -519,86 +487,53 @@ Gcc_backend::Gcc_backend () const_ptr_type_node, const_ptr_type_node, size_type_node, NULL_TREE), -<<<<<<< HEAD 0); -======= - false, false); ->>>>>>> 12e994a7967... Fix indentation // We use __builtin_memmove for copying data. this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove", build_function_type_list (void_type_node, ptr_type_node, const_ptr_type_node, size_type_node, NULL_TREE), -<<<<<<< HEAD 0); -======= - false, false); ->>>>>>> 12e994a7967... Fix indentation // We use __builtin_memset for zeroing data. this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset", build_function_type_list (void_type_node, ptr_type_node, integer_type_node, size_type_node, NULL_TREE), -<<<<<<< HEAD 0); -======= - false, false); ->>>>>>> 12e994a7967... Fix indentation // Used by runtime/internal/sys and math/bits. this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz", build_function_type_list (integer_type_node, unsigned_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); -======= - true, false); ->>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll", build_function_type_list (integer_type_node, long_long_unsigned_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); -======= - true, false); ->>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz", build_function_type_list (integer_type_node, unsigned_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); -======= - true, false); ->>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll", build_function_type_list (integer_type_node, long_long_unsigned_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); -======= - true, false); ->>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount", build_function_type_list (integer_type_node, unsigned_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); -======= - true, false); ->>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll", "popcountll", build_function_type_list (integer_type_node, long_long_unsigned_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", build_function_type_list (uint16_type_node, @@ -612,21 +547,6 @@ Gcc_backend::Gcc_backend () build_function_type_list (uint64_type_node, uint64_type_node, NULL_TREE), builtin_const); -======= - true, false); - this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", - build_function_type_list (uint16_type_node, - uint16_type_node, NULL_TREE), - true, false); - this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32", - build_function_type_list (uint32_type_node, - uint32_type_node, NULL_TREE), - true, false); - this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64", - build_function_type_list (uint64_type_node, - uint64_type_node, NULL_TREE), - true, false); ->>>>>>> 12e994a7967... Fix indentation // We provide some functions for the math library. tree math_function_type @@ -641,7 +561,6 @@ Gcc_backend::Gcc_backend () = build_function_type_list (long_double_type_node, long_double_type_node, long_double_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ACOS, "__builtin_acos", "acos", -<<<<<<< HEAD math_function_type, builtin_const); this->define_builtin (BUILT_IN_ACOSL, "__builtin_acosl", "acosl", math_function_type_long, builtin_const); @@ -685,65 +604,15 @@ Gcc_backend::Gcc_backend () math_function_type_two, builtin_const); this->define_builtin (BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", math_function_type_long_two, builtin_const); -======= - math_function_type, true, false); - this->define_builtin (BUILT_IN_ACOSL, "__builtin_acosl", "acosl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_ASIN, "__builtin_asin", "asin", - math_function_type, true, false); - this->define_builtin (BUILT_IN_ASINL, "__builtin_asinl", "asinl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_ATAN, "__builtin_atan", "atan", - math_function_type, true, false); - this->define_builtin (BUILT_IN_ATANL, "__builtin_atanl", "atanl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_ATAN2, "__builtin_atan2", "atan2", - math_function_type_two, true, false); - this->define_builtin (BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l", - math_function_type_long_two, true, false); - this->define_builtin (BUILT_IN_CEIL, "__builtin_ceil", "ceil", - math_function_type, true, false); - this->define_builtin (BUILT_IN_CEILL, "__builtin_ceill", "ceill", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_COS, "__builtin_cos", "cos", - math_function_type, true, false); - this->define_builtin (BUILT_IN_COSL, "__builtin_cosl", "cosl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_EXP, "__builtin_exp", "exp", - math_function_type, true, false); - this->define_builtin (BUILT_IN_EXPL, "__builtin_expl", "expl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_EXPM1, "__builtin_expm1", "expm1", - math_function_type, true, false); - this->define_builtin (BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_FABS, "__builtin_fabs", "fabs", - math_function_type, true, false); - this->define_builtin (BUILT_IN_FABSL, "__builtin_fabsl", "fabsl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_FLOOR, "__builtin_floor", "floor", - math_function_type, true, false); - this->define_builtin (BUILT_IN_FLOORL, "__builtin_floorl", "floorl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_FMOD, "__builtin_fmod", "fmod", - math_function_type_two, true, false); - this->define_builtin (BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", - math_function_type_long_two, true, false); ->>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp", build_function_type_list (double_type_node, double_type_node, integer_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); -======= - true, false); ->>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl", build_function_type_list (long_double_type_node, long_double_type_node, integer_type_node, NULL_TREE), -<<<<<<< HEAD builtin_const); this->define_builtin (BUILT_IN_LOG, "__builtin_log", "log", math_function_type, builtin_const); @@ -777,47 +646,11 @@ Gcc_backend::Gcc_backend () math_function_type, builtin_const); this->define_builtin (BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", math_function_type_long, builtin_const); -======= - true, false); - this->define_builtin (BUILT_IN_LOG, "__builtin_log", "log", - math_function_type, true, false); - this->define_builtin (BUILT_IN_LOGL, "__builtin_logl", "logl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_LOG1P, "__builtin_log1p", "log1p", - math_function_type, true, false); - this->define_builtin (BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_LOG10, "__builtin_log10", "log10", - math_function_type, true, false); - this->define_builtin (BUILT_IN_LOG10L, "__builtin_log10l", "log10l", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_LOG2, "__builtin_log2", "log2", - math_function_type, true, false); - this->define_builtin (BUILT_IN_LOG2L, "__builtin_log2l", "log2l", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_SIN, "__builtin_sin", "sin", - math_function_type, true, false); - this->define_builtin (BUILT_IN_SINL, "__builtin_sinl", "sinl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", - math_function_type, true, false); - this->define_builtin (BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_TAN, "__builtin_tan", "tan", - math_function_type, true, false); - this->define_builtin (BUILT_IN_TANL, "__builtin_tanl", "tanl", - math_function_type_long, true, false); - this->define_builtin (BUILT_IN_TRUNC, "__builtin_trunc", "trunc", - math_function_type, true, false); - this->define_builtin (BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", - math_function_type_long, true, false); ->>>>>>> 12e994a7967... Fix indentation // We use __builtin_return_address in the thunk we build for // functions which call recover, and for runtime.getcallerpc. t = build_function_type_list (ptr_type_node, unsigned_type_node, NULL_TREE); this->define_builtin (BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", -<<<<<<< HEAD NULL, t, 0); // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp. @@ -829,176 +662,94 @@ Gcc_backend::Gcc_backend () this->define_builtin ( BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL, build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0); -======= - NULL, t, false, false); - - // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp. - t = build_function_type_list (ptr_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t, - false, false); - - // The runtime calls __builtin_extract_return_addr when recording - // the address to which a function returns. - this->define_builtin (BUILT_IN_EXTRACT_RETURN_ADDR, - "__builtin_extract_return_addr", NULL, - build_function_type_list (ptr_type_node, ptr_type_node, - NULL_TREE), - false, false); ->>>>>>> 12e994a7967... Fix indentation // The compiler uses __builtin_trap for some exception handling // cases. this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL, build_function_type (void_type_node, void_list_node), -<<<<<<< HEAD builtin_noreturn); -======= - false, true); ->>>>>>> 12e994a7967... Fix indentation // The runtime uses __builtin_prefetch. this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL, build_varargs_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE), -<<<<<<< HEAD builtin_novops); -======= - false, false); ->>>>>>> 12e994a7967... Fix indentation // The compiler uses __builtin_unreachable for cases that cannot // occur. this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL, build_function_type (void_type_node, void_list_node), -<<<<<<< HEAD builtin_const | builtin_noreturn); -======= - true, true); ->>>>>>> 12e994a7967... Fix indentation // We provide some atomic functions. t = build_function_type_list (uint32_type_node, ptr_type_node, integer_type_node, NULL_TREE); -<<<<<<< HEAD this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t, 0); t = build_function_type_list (uint64_type_node, ptr_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t, 0); -======= - this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t, - false, false); - - t = build_function_type_list (uint64_type_node, ptr_type_node, - integer_type_node, NULL_TREE); - this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t, - false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (void_type_node, ptr_type_node, uint32_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t, -<<<<<<< HEAD 0); -======= - false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (void_type_node, ptr_type_node, uint64_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t, -<<<<<<< HEAD 0); -======= - false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint32_type_node, ptr_type_node, uint32_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL, -<<<<<<< HEAD t, 0); -======= - t, false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint64_type_node, ptr_type_node, uint64_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL, -<<<<<<< HEAD t, 0); -======= - t, false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, uint32_type_node, boolean_type_node, integer_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4, -<<<<<<< HEAD "__atomic_compare_exchange_4", NULL, t, 0); -======= - "__atomic_compare_exchange_4", NULL, t, false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, uint64_type_node, boolean_type_node, integer_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8, -<<<<<<< HEAD "__atomic_compare_exchange_8", NULL, t, 0); -======= - "__atomic_compare_exchange_8", NULL, t, false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint32_type_node, ptr_type_node, uint32_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", -<<<<<<< HEAD NULL, t, 0); -======= - NULL, t, false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint64_type_node, ptr_type_node, uint64_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", -<<<<<<< HEAD NULL, t, 0); -======= - NULL, t, false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (unsigned_char_type_node, ptr_type_node, unsigned_char_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", -<<<<<<< HEAD NULL, t, 0); this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", NULL, t, 0); -======= - NULL, t, false, false); - this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", - NULL, t, false, false); ->>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (unsigned_char_type_node, ptr_type_node, unsigned_char_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL, -<<<<<<< HEAD t, 0); this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, t, 0); -======= - t, false, false); - this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, - t, false, false); ->>>>>>> 12e994a7967... Fix indentation } // Get an unnamed integer type. @@ -1385,13 +1136,9 @@ Gcc_backend::named_type (const std::string &name, Btype *btype, if (type == error_mark_node) return this->error_type (); - // The middle-end expects a basic type to have a name. In Rust every + // The middle-end expects a basic type to have a name. In Go every // basic type will have a name. The first time we see a basic type, -<<<<<<< HEAD - // give it whatever Rust name we have at this point. -======= // give it whatever Go name we have at this point. ->>>>>>> 12e994a7967... Fix indentation if (TYPE_NAME (type) == NULL_TREE && location.gcc_location () == BUILTINS_LOCATION && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE @@ -1837,11 +1584,7 @@ Gcc_backend::unary_expression (Operator op, Bexpression *expr, enum tree_code code; switch (op) { -<<<<<<< HEAD - case OPERATOR_MINUS: { -======= case OPERATOR_MINUS: { ->>>>>>> 12e994a7967... Fix indentation tree computed_type = excess_precision_type (type_tree); if (computed_type != NULL_TREE) { @@ -2173,13 +1916,8 @@ Gcc_backend::call_expression (Bfunction *, // containing fcn for call // This is to support builtin math functions when using 80387 math. tree excess_type = NULL_TREE; if (optimize && TREE_CODE (fndecl) == FUNCTION_DECL -<<<<<<< HEAD && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) && DECL_IS_UNDECLARED_BUILTIN (fndecl) && nargs > 0 -======= - && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) && DECL_IS_BUILTIN (fndecl) - && nargs > 0 ->>>>>>> 12e994a7967... Fix indentation && ((SCALAR_FLOAT_TYPE_P (rettype) && SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[0]))) || (COMPLEX_FLOAT_TYPE_P (rettype) @@ -2682,19 +2420,11 @@ Gcc_backend::non_zero_size_type (tree type) DECL_CONTEXT (field) = type; TYPE_FIELDS (type) = field; layout_type (type); -<<<<<<< HEAD rust_non_zero_struct = type; -======= - go_non_zero_struct = type; ->>>>>>> 12e994a7967... Fix indentation } return rust_non_zero_struct; -<<<<<<< HEAD - case ARRAY_TYPE: { -======= case ARRAY_TYPE: { ->>>>>>> 12e994a7967... Fix indentation tree element_type = non_zero_size_type (TREE_TYPE (type)); return build_array_type_nelts (element_type, 1); } @@ -2802,11 +2532,7 @@ Gcc_backend::global_variable_set_init (Bvariable *var, Bexpression *expr) if (symtab_node::get (var_decl) && symtab_node::get (var_decl)->implicit_section) { -<<<<<<< HEAD set_decl_section_name (var_decl, (const char *) NULL); -======= - set_decl_section_name (var_decl, NULL); ->>>>>>> 12e994a7967... Fix indentation resolve_unique_section (var_decl, compute_reloc_for_constant (expr_tree), 1); } @@ -2921,22 +2647,14 @@ Gcc_backend::temporary_variable (Bfunction *function, Bblock *bblock, else push_cfun (DECL_STRUCT_FUNCTION (decl)); -<<<<<<< HEAD var = create_tmp_var (type_tree, "RUSTTMP"); -======= - var = create_tmp_var (type_tree, "GOTMP"); ->>>>>>> 12e994a7967... Fix indentation pop_cfun (); } else { gcc_assert (bblock != NULL); var = build_decl (location.gcc_location (), VAR_DECL, -<<<<<<< HEAD create_tmp_var_name ("RUSTTMP"), type_tree); -======= - create_tmp_var_name ("GOTMP"), type_tree); ->>>>>>> 12e994a7967... Fix indentation DECL_ARTIFICIAL (var) = 1; DECL_IGNORED_P (var) = 1; TREE_USED (var) = 1; @@ -3330,24 +3048,15 @@ Gcc_backend::function (Btype *fntype, const std::string &name, if (pos == name.length ()) { struct cl_optimization cur_opts; -<<<<<<< HEAD cl_optimization_save (&cur_opts, &global_options, &global_options_set); -======= - cl_optimization_save (&cur_opts, &global_options); ->>>>>>> 12e994a7967... Fix indentation global_options.x_optimize_size = 1; global_options.x_optimize_fast = 0; global_options.x_optimize_debug = 0; DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl) -<<<<<<< HEAD = build_optimization_node (&global_options, &global_options_set); cl_optimization_restore (&global_options, &global_options_set, &cur_opts); -======= - = build_optimization_node (&global_options); - cl_optimization_restore (&global_options, &cur_opts); ->>>>>>> 12e994a7967... Fix indentation } } diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index 66895dc..91c77bc 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -155,7 +155,6 @@ grs_langhook_parse_file (void) { fprintf (stderr, "Preparing to parse files. \n"); - // grs_parse_files(num_in_fnames, in_fnames); session.parse_files (num_in_fnames, in_fnames); } @@ -183,7 +182,7 @@ grs_langhook_type_for_mode (machine_mode mode, int unsignedp) return unsignedp ? unsigned_intSI_type_node : intSI_type_node; if (mode == TYPE_MODE ( - intDI_type_node)) // double integer mode - eight-byte integer + intDI_type_node)) // double integer mode - eight-byte integer return unsignedp ? unsigned_intDI_type_node : intDI_type_node; if (mode == TYPE_MODE (intTI_type_node)) // tetra integer mode - 16-byte integer diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index b0cfca2..1e49271 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -10,6 +10,7 @@ #include "rust-lex.h" #include "rust-parse.h" #include "rust-resolution.h" +#include "rust-compile.h" #include "rust-target.h" @@ -18,6 +19,9 @@ extern Linemap * rust_get_linemap (); +extern Backend * +rust_get_backend (); + namespace Rust { // Simple wrapper for FILE* that simplifies destruction. struct RAIIFile @@ -410,6 +414,8 @@ Session::parse_file (const char *filename) fatal_error (UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); } + Backend *backend = rust_get_backend (); + // parse file here // create lexer and parser - these are file-specific and so aren't instance // variables @@ -487,6 +493,9 @@ Session::parse_file (const char *filename) // TODO: what do I dump here? resolved names? AST with resolved names? return; } + + // do compile + Compile::Compilation::Compile (parsed_crate, backend); } // Checks whether 'cfg' attribute prevents compilation. diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index ee43232..2352267 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -9,7 +9,7 @@ #include "rust-system.h" #include "rust-linemap.h" -#include "backend.h" +#include "rust-backend.h" #include #include @@ -18,184 +18,219 @@ #include namespace Rust { - // parser forward decl - class Parser; - // crate forward decl - namespace AST { - struct Crate; - } - - // Data related to target, most useful for conditional compilation and whatever. - struct TargetOptions { - // TODO: maybe make private and access through helpers to allow changes to impl - std::unordered_map> features; - - public: - // Returns whether a key is defined in the feature set. - bool has_key(std::string key) const { - return features.find(key) != features.end(); - } - - // Returns whether a key exists with the given value in the feature set. - bool has_key_value_pair(std::string key, std::string value) const { - auto it = features.find(key); - if (it != features.end()) { - auto set = it->second; - auto it2 = set.find(value); - if (it2 != set.end()) - return true; - } - return false; - } - - // Returns the singular value from the key, or if the key has multiple, an empty string. - std::string get_singular_value(std::string key) const { - auto it = features.find(key); - if (it != features.end()) { - auto set = it->second; - if (set.size() == 1) - return *set.begin(); - } - return ""; - } - - // Returns all values associated with a key (including none), or an empty set if no key is found. - std::unordered_set< ::std::string> get_values_for_key(std::string key) const { - auto it = features.find(key); - if (it != features.end()) { - return it->second; - } - return {}; - } - - /* Inserts a key (no value) into the feature set. This will do nothing if the key already exists. - * This returns whether the insertion was successful (i.e. whether key already existed). */ - bool insert_key(std::string key) { - return features.insert(std::make_pair(key, std::unordered_set())).second; - } - - // Inserts a key-value pair into the feature set. - void insert_key_value_pair(std::string key, std::string value) { - auto existing_set = get_values_for_key(key); - existing_set.insert(std::move(value)); - features[std::move(key)] = std::move(existing_set); - } - - // Dump all target options to stderr. - void dump_target_options() const; - - // Creates derived values and implicit enables after all target info is added (e.g. "unix"). - void init_derived_values(); - - // Enables all requirements for the feature given, and will enable feature itself if not enabled. - void enable_implicit_feature_reqs(std::string feature); - - /* According to reference, Rust uses either multi-map key-values or just values (although - * values may be aliases for a key-value value). This seems like overkill. Thus, depending on - * whether the attributes used in cfg are fixed or not, I think I'll either put each - * non-multimap "key-value" as a separate field and have the multimap "key-values" in a - * regular map for that one key, or actually use a multimap. - * - * rustc itself uses a set of key-value tuples where the second tuple element is optional. - * This gets rid of the requirement to make a multi-map, I guess, but seems like it might make - * search slow (unless all "is defined"-only ones have empty string as second element). */ - /* cfg attributes: - * - target_arch: single value - * - target_feature: multiple values possible - * - target_os: single value - * - target_family: single value (or no value?) - * - unix: set when target_family = "unix" - * - windows: set when target_family = "windows" - * - if these are just syntactic sugar, then maybe have a separate set or map for this kind - * of stuff - * - target_env: set when needed for disambiguation about ABI - usually empty string for GNU, - * complicated - * - seems to be a single value (if any) - * - target_endian: single value; "little" or "big" - * - target_pointer_width: single value, "32" for 32-bit pointers, etc. - * - target_vendor, single value - * - test: set when testing is being done - * - again, seems similar to a "is defined" rather than "is equal to" like unix - * - debug_assertions: seems to "is defined" - * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is defined" */ - }; - - // Defines compiler options (e.g. dump, etc.). - struct CompileOptions { - // TODO: use bitfield for smaller memory requirements? - - // FIXME: this is set up for "instead of" dumping - in future, dumps should not inhibit - // compilation - enum DumpOptions { - NO_DUMP, - LEXER_DUMP, - PARSER_AST_DUMP, - REGISTER_PLUGINS_DUMP, - INJECTION_DUMP, - EXPANSION_DUMP, - NAME_RESOLUTION_DUMP, - TARGET_OPTION_DUMP, - // TODO: add more? - } dump_option; - - // configuration options - actually useful for conditional compilation and whatever - // data related to target arch, features, os, family, env, endian, pointer width, vendor - TargetOptions target_data; - bool enable_test = false; - bool debug_assertions = false; - bool proc_macro = false; - }; - - /* Defines a compiler session. This is for a single compiler invocation, so potentially includes - * parsing multiple crates. */ - struct Session { - CompileOptions options; - // This should really be in a per-crate storage area but it is wiped with every file so eh. - ::std::string injected_crate_name; - - // backend wrapper to GCC GENERIC - Backend* backend; - - // backend linemap - Linemap* linemap; - - // TODO: replace raw pointers with smart pointers? - - public: - /* Initialise compiler session. Corresponds to langhook grs_langhook_init(). Note that this is - * called after option handling. */ - void init(); - bool handle_option(enum opt_code code, const char* arg, HOST_WIDE_INT value, int kind, - location_t loc, const struct cl_option_handlers* handlers); - void parse_files(int num_files, const char** files); - void init_options(); - - private: - // TODO: should this be private or public? - void parse_file(const char* filename); - bool enable_dump(::std::string arg); - - void debug_dump_load_crates(Parser& parser); - - void implicitly_enable_feature(::std::string feature_name); - void enable_features(); - - // pipeline stages - TODO maybe move? - /* Register plugins pipeline stage. TODO maybe move to another object? Currently dummy stage. - * In future will handle attribute injection (top-level inner attribute creation from command - * line arguments), setting options maybe, registering lints maybe, loading plugins maybe. */ - void register_plugins(AST::Crate& crate); - /* Injection pipeline stage. TODO maybe move to another object? Maybe have some lint checks - * (in future, obviously), register builtin macros, crate injection. */ - void injection(AST::Crate& crate); - /* Expansion pipeline stage. TODO maybe move to another object? Expands all macros, maybe - * build test harness in future, AST validation, maybe create macro crate (if not rustdoc).*/ - void expansion(AST::Crate& crate); - /* Name resolution pipeline stage. TODO maybe move to another object. Performs name - * resolution, maybe complete gated feature checking, maybe create buffered lints in future. - */ - void name_resolution(AST::Crate& crate); - }; +// parser forward decl +class Parser; +// crate forward decl +namespace AST { +struct Crate; } +// Data related to target, most useful for conditional compilation and +// whatever. +struct TargetOptions +{ + // TODO: maybe make private and access through helpers to allow changes to + // impl + std::unordered_map > features; + +public: + // Returns whether a key is defined in the feature set. + bool has_key (std::string key) const + { + return features.find (key) != features.end (); + } + + // Returns whether a key exists with the given value in the feature set. + bool has_key_value_pair (std::string key, std::string value) const + { + auto it = features.find (key); + if (it != features.end ()) + { + auto set = it->second; + auto it2 = set.find (value); + if (it2 != set.end ()) + return true; + } + return false; + } + + // Returns the singular value from the key, or if the key has multiple, an + // empty string. + std::string get_singular_value (std::string key) const + { + auto it = features.find (key); + if (it != features.end ()) + { + auto set = it->second; + if (set.size () == 1) + return *set.begin (); + } + return ""; + } + + // Returns all values associated with a key (including none), or an empty set + // if no key is found. + std::unordered_set< ::std::string> get_values_for_key (std::string key) const + { + auto it = features.find (key); + if (it != features.end ()) + { + return it->second; + } + return {}; + } + + /* Inserts a key (no value) into the feature set. This will do nothing if the + * key already exists. + * This returns whether the insertion was successful (i.e. whether key already + * existed). */ + bool insert_key (std::string key) + { + return features + .insert (std::make_pair (key, std::unordered_set ())) + .second; + } + + // Inserts a key-value pair into the feature set. + void insert_key_value_pair (std::string key, std::string value) + { + auto existing_set = get_values_for_key (key); + existing_set.insert (std::move (value)); + features[std::move (key)] = std::move (existing_set); + } + + // Dump all target options to stderr. + void dump_target_options () const; + + // Creates derived values and implicit enables after all target info is added + // (e.g. "unix"). + void init_derived_values (); + + // Enables all requirements for the feature given, and will enable feature + // itself if not enabled. + void enable_implicit_feature_reqs (std::string feature); + + /* According to reference, Rust uses either multi-map key-values or just + * values (although values may be aliases for a key-value value). This seems + * like overkill. Thus, depending on whether the attributes used in cfg are + * fixed or not, I think I'll either put each non-multimap "key-value" as a + * separate field and have the multimap "key-values" in a regular map for that + * one key, or actually use a multimap. + * + * rustc itself uses a set of key-value tuples where the second tuple element + * is optional. This gets rid of the requirement to make a multi-map, I guess, + * but seems like it might make + * search slow (unless all "is defined"-only ones have empty string as second + * element). */ + /* cfg attributes: + * - target_arch: single value + * - target_feature: multiple values possible + * - target_os: single value + * - target_family: single value (or no value?) + * - unix: set when target_family = "unix" + * - windows: set when target_family = "windows" + * - if these are just syntactic sugar, then maybe have a separate set or map + * for this kind of stuff + * - target_env: set when needed for disambiguation about ABI - usually empty + * string for GNU, complicated + * - seems to be a single value (if any) + * - target_endian: single value; "little" or "big" + * - target_pointer_width: single value, "32" for 32-bit pointers, etc. + * - target_vendor, single value + * - test: set when testing is being done + * - again, seems similar to a "is defined" rather than "is equal to" like + * unix + * - debug_assertions: seems to "is defined" + * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is defined" + */ +}; + +// Defines compiler options (e.g. dump, etc.). +struct CompileOptions +{ + // TODO: use bitfield for smaller memory requirements? + + // FIXME: this is set up for "instead of" dumping - in future, dumps should + // not inhibit compilation + enum DumpOptions + { + NO_DUMP, + LEXER_DUMP, + PARSER_AST_DUMP, + REGISTER_PLUGINS_DUMP, + INJECTION_DUMP, + EXPANSION_DUMP, + NAME_RESOLUTION_DUMP, + TARGET_OPTION_DUMP, + // TODO: add more? + } dump_option; + + // configuration options - actually useful for conditional compilation and + // whatever data related to target arch, features, os, family, env, endian, + // pointer width, vendor + TargetOptions target_data; + bool enable_test = false; + bool debug_assertions = false; + bool proc_macro = false; +}; + +/* Defines a compiler session. This is for a single compiler invocation, so + * potentially includes parsing multiple crates. */ +struct Session +{ + CompileOptions options; + // This should really be in a per-crate storage area but it is wiped with + // every file so eh. + ::std::string injected_crate_name; + + // backend wrapper to GCC GENERIC + Backend *backend; + + // backend linemap + Linemap *linemap; + + // TODO: replace raw pointers with smart pointers? + +public: + /* Initialise compiler session. Corresponds to langhook grs_langhook_init(). + * Note that this is called after option handling. */ + void init (); + bool handle_option (enum opt_code code, const char *arg, HOST_WIDE_INT value, + int kind, location_t loc, + const struct cl_option_handlers *handlers); + void parse_files (int num_files, const char **files); + void init_options (); + +private: + // TODO: should this be private or public? + void parse_file (const char *filename); + bool enable_dump (::std::string arg); + + void debug_dump_load_crates (Parser &parser); + + void implicitly_enable_feature (::std::string feature_name); + void enable_features (); + + // pipeline stages - TODO maybe move? + /* Register plugins pipeline stage. TODO maybe move to another object? + * Currently dummy stage. In future will handle attribute injection (top-level + * inner attribute creation from command line arguments), setting options + * maybe, registering lints maybe, loading plugins maybe. */ + void register_plugins (AST::Crate &crate); + /* Injection pipeline stage. TODO maybe move to another object? Maybe have + * some lint checks (in future, obviously), register builtin macros, crate + * injection. */ + void injection (AST::Crate &crate); + /* Expansion pipeline stage. TODO maybe move to another object? Expands all + * macros, maybe build test harness in future, AST validation, maybe create + * macro crate (if not rustdoc).*/ + void expansion (AST::Crate &crate); + /* Name resolution pipeline stage. TODO maybe move to another object. Performs + * name resolution, maybe complete gated feature checking, maybe create + * buffered lints in future. + */ + void name_resolution (AST::Crate &crate); +}; +} // namespace Rust + #endif -- cgit v1.1