| //===-- go-llvm-bstatement.h - decls for gofrontend 'Bstatement' class ----===// |
| // |
| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Defines Bstatement and related classes. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVMGOFRONTEND_GO_LLVM_BSTATEMENT_H |
| #define LLVMGOFRONTEND_GO_LLVM_BSTATEMENT_H |
| |
| // Currently these need to be included before backend.h |
| #include "go-llvm-linemap.h" |
| #include "go-location.h" |
| #include "go-llvm-btype.h" |
| //#include "go-llvm-bexpression.h" |
| #include "go-llvm-bnode.h" |
| |
| #include "backend.h" |
| |
| namespace llvm { |
| class Function; |
| class Instruction; |
| class Type; |
| class Value; |
| class raw_ostream; |
| } |
| |
| // Class Bstatement encapsulates the IR for a statement, storing zero |
| // or more component Bexpressions, along with state related to |
| // statement control flow (if / switch / goto, etc). The specific |
| // contents/children of a given Bstatement are determined by its |
| // NodeFlavor (value of Bnode::flavor()). |
| // |
| // In the current gofrontend implementation, there is an extremely |
| // fluzzy/fluid line between Bexpression's, Bblocks, and Bstatements. |
| // For example, you can take a Bblock and turn it into a statement via |
| // Backend::block_statement. You can also combine an existing |
| // Bstatement with a Bexpression to form a second Bexpression via |
| // Backend::compound_expression. This is most likely due to the fact |
| // that the first backend (gcc) selected as a target for gofrontend |
| // uses a tree intermediate representation, where blocks, expressions, |
| // and statements are all simply tree fragments. With LLVM on the |
| // other hand, it is not so straightforward to have chunks of IR |
| // morphing back end forth between statements, expressions, and |
| // blocks. |
| |
| class Bstatement : public Bnode { |
| public: |
| // no public constructor, use BnodeBuilder instead |
| virtual ~Bstatement(); |
| |
| // Function this statement is part of |
| Bfunction *function() const { return function_; } |
| |
| // dump with source line info |
| void srcDump(Llvm_linemap *); |
| |
| // If this is an expression statement (flavor N_ExprStmt), return |
| // a pointer to the Bexpression it contains. |
| Bexpression *getExprStmtExpr(); |
| |
| // If this is a return statement (flavor N_ReturnStmt), return |
| // a pointer to the Bexpression it contains. |
| Bexpression *getReturnStmtExpr(); |
| |
| // If this is an if statement (flavor N_IfStmt), return |
| // components of the "if" (condition, true block, false block). |
| Bexpression *getIfStmtCondition(); |
| Bstatement *getIfStmtTrueBlock(); |
| Bstatement *getIfStmtFalseBlock(); |
| |
| // If this is a switch statement (flavor N_SwitchStmt), return |
| // the Bexpresson for the value we're switching on, along |
| // with info on the number of cases, Bexpressions for each case, |
| // and Bstatement for each case. |
| Bexpression *getSwitchStmtValue(); |
| unsigned getSwitchStmtNumCases(); |
| std::vector<Bexpression *> getSwitchStmtNthCase(unsigned idx); |
| Bstatement *getSwitchStmtNthStmt(unsigned idx); |
| |
| // If this is a defer statement (flavor N_DeferStmt), return |
| // components of the defer. |
| Bexpression *getDeferStmtUndeferCall(); |
| Bexpression *getDeferStmtDeferCall(); |
| |
| // If this is an exception handling statement (flavor N_ExcepStmt), return |
| // components of the statement. |
| Bstatement *getExcepStmtBody(); |
| Bstatement *getExcepStmtOnException(); |
| Bstatement *getExcepStmtFinally(); |
| |
| // If this is a goto statement (flavor N_GotoStmt), return |
| // the target label for the goto. |
| Blabel *getGotoStmtTargetLabel(); |
| |
| // If this is a label statement (flavor N_LabelStmt), return |
| // the label defined by this stmt. |
| Blabel *getLabelStmtDefinedLabel(); |
| |
| // Generic hook for collecting all statements that are children of |
| // this statement. Used when walking statements to assign |
| // instructions to LLVM blocks. |
| std::vector<Bstatement *> getChildStmts(); |
| |
| protected: |
| friend class BnodeBuilder; |
| Bstatement(NodeFlavor fl, Bfunction *func, |
| const std::vector<Bnode *> &kids, Location loc); |
| |
| private: |
| Bexpression *getNthChildAsExpr(NodeFlavor fl, unsigned cidx); |
| Bstatement *getNthChildAsStmt(NodeFlavor fl, unsigned cidx); |
| |
| private: |
| Bfunction *function_; |
| }; |
| |
| typedef unsigned LabelId; |
| |
| // Back end label class. Encapsulates a label referred to by a label |
| // definition statement and/or some set of goto statements. |
| |
| class Blabel { |
| public: |
| Blabel(const Bfunction *function, LabelId lab, Location loc) |
| : function_(const_cast<Bfunction *>(function)), |
| placeholder_(nullptr), lab_(lab), location_(loc) {} |
| LabelId label() const { return lab_; } |
| Bfunction *function() { return function_; } |
| Location location() const { return location_; } |
| llvm::Value *placeholder() const { return placeholder_; } |
| void setPlaceholder(llvm::Value *ph); |
| |
| private: |
| Bfunction *function_; |
| llvm::Value *placeholder_; |
| LabelId lab_; |
| Location location_; |
| }; |
| |
| // A Bblock is essentially just a compound statement |
| |
| class Bblock : public Bstatement { |
| public: |
| // no public constructor; use BnodeBuilder::mkBlock to create a |
| // block, BnodeBuilder::addStatementToBlock to add stmts to it. |
| virtual ~Bblock() { } |
| |
| // Local variables for this block |
| const std::vector<Bvariable *> &vars() const { return vars_; } |
| |
| // Temporary vars can be tacked into an existing block via a |
| // the backend temporary_variable() method-- allow for this here. |
| void addTemporaryVariable(Bvariable *var); |
| |
| void setError() { error_ = true; } |
| bool hasError() { return error_; } |
| |
| private: |
| friend class BnodeBuilder; |
| Bblock(Bfunction *func, |
| const std::vector<Bvariable *> &vars, |
| Location loc); |
| |
| private: |
| std::vector<Bvariable *> vars_; |
| bool error_; |
| }; |
| |
| #endif // LLVMGOFRONTEND_GO_LLVM_BSTATEMENT_H |