lowering.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/lowering/lowering.h"
  5. #include "toolchain/semantics/semantics_ir.h"
  6. namespace Carbon {
  7. Lowering::Lowering(llvm::LLVMContext& llvm_context, llvm::StringRef module_name,
  8. const SemanticsIR& semantics_ir)
  9. : llvm_context_(&llvm_context),
  10. llvm_module_(std::make_unique<llvm::Module>(module_name, llvm_context)),
  11. builder_(llvm_context),
  12. semantics_ir_(&semantics_ir),
  13. lowered_nodes_(semantics_ir_->nodes_size(), nullptr) {
  14. CARBON_CHECK(!semantics_ir.has_errors())
  15. << "Generating LLVM IR from invalid SemanticsIR is unsupported.";
  16. }
  17. auto Lowering::Run() -> std::unique_ptr<llvm::Module> {
  18. CARBON_CHECK(llvm_module_) << "Run can only be called once.";
  19. LowerBlock(semantics_ir_->top_node_block_id());
  20. while (!todo_blocks_.empty()) {
  21. auto [llvm_block, block_id] = todo_blocks_.pop_back_val();
  22. builder_.SetInsertPoint(llvm_block);
  23. LowerBlock(block_id);
  24. }
  25. return std::move(llvm_module_);
  26. }
  27. auto Lowering::LowerBlock(SemanticsNodeBlockId block_id) -> void {
  28. for (const auto& node_id : semantics_ir_->GetNodeBlock(block_id)) {
  29. auto node = semantics_ir_->GetNode(node_id);
  30. switch (node.kind()) {
  31. #define CARBON_SEMANTICS_NODE_KIND(Name) \
  32. case SemanticsNodeKind::Name: \
  33. Handle##Name##Node(node_id, node); \
  34. break;
  35. #include "toolchain/semantics/semantics_node_kind.def"
  36. }
  37. }
  38. }
  39. auto Lowering::LowerNodeToType(SemanticsNodeId node_id) -> llvm::Type* {
  40. CARBON_CHECK(node_id.is_valid());
  41. switch (node_id.index) {
  42. case SemanticsBuiltinKind::EmptyTuple.AsInt():
  43. // TODO: Should probably switch this to an actual empty tuple in the
  44. // future, but it's implemented as void for now.
  45. return builder_.getVoidTy();
  46. case SemanticsBuiltinKind::IntegerType.AsInt():
  47. // TODO: Handle different sizes.
  48. return builder_.getInt32Ty();
  49. default:
  50. CARBON_FATAL() << "Cannot use node as type: " << node_id;
  51. }
  52. }
  53. auto Lowering::HandleInvalidNode(SemanticsNodeId /*node_id*/,
  54. SemanticsNode /*node*/) -> void {
  55. llvm_unreachable("never in actual IR");
  56. }
  57. auto Lowering::HandleCrossReferenceNode(SemanticsNodeId /*node_id*/,
  58. SemanticsNode node) -> void {
  59. CARBON_FATAL() << "TODO: Add support: " << node;
  60. }
  61. auto Lowering::HandleAssignNode(SemanticsNodeId /*node_id*/, SemanticsNode node)
  62. -> void {
  63. CARBON_FATAL() << "TODO: Add support: " << node;
  64. }
  65. auto Lowering::HandleBinaryOperatorAddNode(SemanticsNodeId /*node_id*/,
  66. SemanticsNode node) -> void {
  67. CARBON_FATAL() << "TODO: Add support: " << node;
  68. }
  69. auto Lowering::HandleBindNameNode(SemanticsNodeId /*node_id*/,
  70. SemanticsNode node) -> void {
  71. CARBON_FATAL() << "TODO: Add support: " << node;
  72. }
  73. auto Lowering::HandleBuiltinNode(SemanticsNodeId /*node_id*/,
  74. SemanticsNode node) -> void {
  75. CARBON_FATAL() << "TODO: Add support: " << node;
  76. }
  77. auto Lowering::HandleCallNode(SemanticsNodeId /*node_id*/, SemanticsNode node)
  78. -> void {
  79. CARBON_FATAL() << "TODO: Add support: " << node;
  80. }
  81. auto Lowering::HandleCodeBlockNode(SemanticsNodeId /*node_id*/,
  82. SemanticsNode node) -> void {
  83. CARBON_FATAL() << "TODO: Add support: " << node;
  84. }
  85. auto Lowering::HandleFunctionDeclarationNode(SemanticsNodeId /*node_id*/,
  86. SemanticsNode node) -> void {
  87. auto [name_id, callable_id] = node.GetAsFunctionDeclaration();
  88. auto callable = semantics_ir_->GetCallable(callable_id);
  89. // TODO: Lower type information for the arguments prior to building args.
  90. auto param_refs = semantics_ir_->GetNodeBlock(callable.param_refs_id);
  91. llvm::SmallVector<llvm::Type*> args;
  92. args.resize_for_overwrite(param_refs.size());
  93. for (int i = 0; i < static_cast<int>(param_refs.size()); ++i) {
  94. args[i] = LowerNodeToType(semantics_ir_->GetNode(param_refs[i]).type_id());
  95. }
  96. llvm::Type* return_type = LowerNodeToType(
  97. callable.return_type_id.is_valid() ? callable.return_type_id
  98. : SemanticsNodeId::BuiltinEmptyTuple);
  99. llvm::FunctionType* function_type =
  100. llvm::FunctionType::get(return_type, args, /*isVarArg=*/false);
  101. auto* function = llvm::Function::Create(
  102. function_type, llvm::Function::ExternalLinkage,
  103. semantics_ir_->GetString(name_id), llvm_module_.get());
  104. // Set parameter names.
  105. for (int i = 0; i < static_cast<int>(param_refs.size()); ++i) {
  106. auto [param_name_id, _] =
  107. semantics_ir_->GetNode(param_refs[i]).GetAsBindName();
  108. function->getArg(i)->setName(semantics_ir_->GetString(param_name_id));
  109. }
  110. }
  111. auto Lowering::HandleFunctionDefinitionNode(SemanticsNodeId /*node_id*/,
  112. SemanticsNode node) -> void {
  113. auto [declaration_id, body_block_id] = node.GetAsFunctionDefinition();
  114. auto [name_id, callable_id] =
  115. semantics_ir_->GetNode(declaration_id).GetAsFunctionDeclaration();
  116. llvm::Function* function =
  117. llvm_module_->getFunction(semantics_ir_->GetString(name_id));
  118. // Create a new basic block to start insertion into.
  119. llvm::BasicBlock* body =
  120. llvm::BasicBlock::Create(*llvm_context_, "entry", function);
  121. todo_blocks_.push_back({body, body_block_id});
  122. }
  123. auto Lowering::HandleIntegerLiteralNode(SemanticsNodeId node_id,
  124. SemanticsNode node) -> void {
  125. SemanticsIntegerLiteralId int_id = node.GetAsIntegerLiteral();
  126. llvm::APInt i = semantics_ir_->GetIntegerLiteral(int_id);
  127. llvm::Value* v =
  128. llvm::ConstantInt::get(builder_.getInt32Ty(), i.getLimitedValue());
  129. lowered_nodes_[node_id.index] = v;
  130. }
  131. auto Lowering::HandleRealLiteralNode(SemanticsNodeId /*node_id*/,
  132. SemanticsNode node) -> void {
  133. CARBON_FATAL() << "TODO: Add support: " << node;
  134. }
  135. auto Lowering::HandleReturnNode(SemanticsNodeId /*node_id*/,
  136. SemanticsNode /*node*/) -> void {
  137. builder_.CreateRetVoid();
  138. }
  139. auto Lowering::HandleReturnExpressionNode(SemanticsNodeId /*node_id*/,
  140. SemanticsNode node) -> void {
  141. SemanticsNodeId expr_id = node.GetAsReturnExpression();
  142. builder_.CreateRet(lowered_nodes_[expr_id.index]);
  143. }
  144. auto Lowering::HandleStringLiteralNode(SemanticsNodeId /*node_id*/,
  145. SemanticsNode node) -> void {
  146. CARBON_FATAL() << "TODO: Add support: " << node;
  147. }
  148. auto Lowering::HandleStructMemberAccessNode(SemanticsNodeId /*node_id*/,
  149. SemanticsNode node) -> void {
  150. CARBON_FATAL() << "TODO: Add support: " << node;
  151. }
  152. auto Lowering::HandleStructTypeNode(SemanticsNodeId /*node_id*/,
  153. SemanticsNode node) -> void {
  154. CARBON_FATAL() << "TODO: Add support: " << node;
  155. }
  156. auto Lowering::HandleStructTypeFieldNode(SemanticsNodeId /*node_id*/,
  157. SemanticsNode node) -> void {
  158. CARBON_FATAL() << "TODO: Add support: " << node;
  159. }
  160. auto Lowering::HandleStructValueNode(SemanticsNodeId /*node_id*/,
  161. SemanticsNode node) -> void {
  162. CARBON_FATAL() << "TODO: Add support: " << node;
  163. }
  164. auto Lowering::HandleStubReferenceNode(SemanticsNodeId /*node_id*/,
  165. SemanticsNode node) -> void {
  166. CARBON_FATAL() << "TODO: Add support: " << node;
  167. }
  168. auto Lowering::HandleVarStorageNode(SemanticsNodeId /*node_id*/,
  169. SemanticsNode node) -> void {
  170. CARBON_FATAL() << "TODO: Add support: " << node;
  171. }
  172. } // namespace Carbon