lowering.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. CARBON_CHECK(!semantics_ir.has_errors())
  14. << "Generating LLVM IR from invalid SemanticsIR is unsupported.";
  15. }
  16. auto Lowering::Run() -> std::unique_ptr<llvm::Module> {
  17. CARBON_CHECK(llvm_module_) << "Run can only be called once.";
  18. LowerBlock(semantics_ir_->top_node_block_id());
  19. while (!todo_blocks_.empty()) {
  20. auto [llvm_block, block_id] = todo_blocks_.pop_back_val();
  21. builder_.SetInsertPoint(llvm_block);
  22. LowerBlock(block_id);
  23. }
  24. return std::move(llvm_module_);
  25. }
  26. auto Lowering::LowerBlock(SemanticsNodeBlockId block_id) -> void {
  27. for (const auto& node_id : semantics_ir_->GetNodeBlock(block_id)) {
  28. auto node = semantics_ir_->GetNode(node_id);
  29. switch (node.kind()) {
  30. #define CARBON_SEMANTICS_NODE_KIND(Name) \
  31. case SemanticsNodeKind::Name: \
  32. Handle##Name##Node(node_id, node); \
  33. break;
  34. #include "toolchain/semantics/semantics_node_kind.def"
  35. }
  36. }
  37. }
  38. auto Lowering::HandleInvalidNode(SemanticsNodeId /*node_id*/,
  39. SemanticsNode /*node*/) -> void {
  40. llvm_unreachable("never in actual IR");
  41. }
  42. auto Lowering::HandleCrossReferenceNode(SemanticsNodeId /*node_id*/,
  43. SemanticsNode node) -> void {
  44. CARBON_FATAL() << "TODO: Add support: " << node;
  45. }
  46. auto Lowering::HandleAssignNode(SemanticsNodeId /*node_id*/, SemanticsNode node)
  47. -> void {
  48. CARBON_FATAL() << "TODO: Add support: " << node;
  49. }
  50. auto Lowering::HandleBinaryOperatorAddNode(SemanticsNodeId /*node_id*/,
  51. SemanticsNode node) -> void {
  52. CARBON_FATAL() << "TODO: Add support: " << node;
  53. }
  54. auto Lowering::HandleBindNameNode(SemanticsNodeId /*node_id*/,
  55. SemanticsNode node) -> void {
  56. CARBON_FATAL() << "TODO: Add support: " << node;
  57. }
  58. auto Lowering::HandleBuiltinNode(SemanticsNodeId /*node_id*/,
  59. SemanticsNode node) -> void {
  60. CARBON_FATAL() << "TODO: Add support: " << node;
  61. }
  62. auto Lowering::HandleCallNode(SemanticsNodeId /*node_id*/, SemanticsNode node)
  63. -> void {
  64. CARBON_FATAL() << "TODO: Add support: " << node;
  65. }
  66. auto Lowering::HandleCodeBlockNode(SemanticsNodeId /*node_id*/,
  67. SemanticsNode node) -> void {
  68. CARBON_FATAL() << "TODO: Add support: " << node;
  69. }
  70. auto Lowering::HandleFunctionDeclarationNode(SemanticsNodeId /*node_id*/,
  71. SemanticsNode node) -> void {
  72. auto [name_id, callable_id] = node.GetAsFunctionDeclaration();
  73. auto callable = semantics_ir_->GetCallable(callable_id);
  74. llvm::SmallVector<llvm::Type*> args;
  75. // Note, when handling non-empty parameters, we'll also want to set names.
  76. CARBON_CHECK(callable.param_refs_id == SemanticsNodeBlockId::Empty)
  77. << "TODO: Handle non-empty parameters.";
  78. CARBON_CHECK(callable.return_type_id == SemanticsNodeId::BuiltinIntegerType)
  79. << "TODO: Handle non-i32 return types.";
  80. llvm::Type* return_type = builder_.getInt32Ty();
  81. llvm::FunctionType* function_type =
  82. llvm::FunctionType::get(return_type, args, /*isVarArg=*/false);
  83. llvm::Function::Create(function_type, llvm::Function::ExternalLinkage,
  84. semantics_ir_->GetString(name_id), llvm_module_.get());
  85. // TODO: Name arguments.
  86. }
  87. auto Lowering::HandleFunctionDefinitionNode(SemanticsNodeId /*node_id*/,
  88. SemanticsNode node) -> void {
  89. auto [declaration_id, body_block_id] = node.GetAsFunctionDefinition();
  90. auto [name_id, callable_id] =
  91. semantics_ir_->GetNode(declaration_id).GetAsFunctionDeclaration();
  92. llvm::Function* function =
  93. llvm_module_->getFunction(semantics_ir_->GetString(name_id));
  94. // Create a new basic block to start insertion into.
  95. llvm::BasicBlock* body =
  96. llvm::BasicBlock::Create(*llvm_context_, "entry", function);
  97. todo_blocks_.push_back({body, body_block_id});
  98. }
  99. auto Lowering::HandleIntegerLiteralNode(SemanticsNodeId node_id,
  100. SemanticsNode node) -> void {
  101. SemanticsIntegerLiteralId int_id = node.GetAsIntegerLiteral();
  102. llvm::APInt i = semantics_ir_->GetIntegerLiteral(int_id);
  103. llvm::Value* v =
  104. llvm::ConstantInt::get(builder_.getInt32Ty(), i.getLimitedValue());
  105. node_values_[node_id] = v;
  106. }
  107. auto Lowering::HandleRealLiteralNode(SemanticsNodeId /*node_id*/,
  108. SemanticsNode node) -> void {
  109. CARBON_FATAL() << "TODO: Add support: " << node;
  110. }
  111. auto Lowering::HandleReturnNode(SemanticsNodeId /*node_id*/, SemanticsNode node)
  112. -> void {
  113. CARBON_FATAL() << "TODO: Add support: " << node;
  114. }
  115. auto Lowering::HandleReturnExpressionNode(SemanticsNodeId /*node_id*/,
  116. SemanticsNode node) -> void {
  117. SemanticsNodeId expr_id = node.GetAsReturnExpression();
  118. builder_.CreateRet(node_values_[expr_id]);
  119. }
  120. auto Lowering::HandleStringLiteralNode(SemanticsNodeId /*node_id*/,
  121. SemanticsNode node) -> void {
  122. CARBON_FATAL() << "TODO: Add support: " << node;
  123. }
  124. auto Lowering::HandleVarStorageNode(SemanticsNodeId /*node_id*/,
  125. SemanticsNode node) -> void {
  126. CARBON_FATAL() << "TODO: Add support: " << node;
  127. }
  128. } // namespace Carbon