file_context.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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/lower/file_context.h"
  5. #include "common/vlog.h"
  6. #include "llvm/ADT/STLExtras.h"
  7. #include "llvm/ADT/Sequence.h"
  8. #include "toolchain/lower/function_context.h"
  9. #include "toolchain/sem_ir/entry_point.h"
  10. #include "toolchain/sem_ir/file.h"
  11. #include "toolchain/sem_ir/node.h"
  12. #include "toolchain/sem_ir/node_kind.h"
  13. namespace Carbon::Lower {
  14. FileContext::FileContext(llvm::LLVMContext& llvm_context,
  15. llvm::StringRef module_name,
  16. const SemIR::File& semantics_ir,
  17. llvm::raw_ostream* vlog_stream)
  18. : llvm_context_(&llvm_context),
  19. llvm_module_(std::make_unique<llvm::Module>(module_name, llvm_context)),
  20. semantics_ir_(&semantics_ir),
  21. vlog_stream_(vlog_stream) {
  22. CARBON_CHECK(!semantics_ir.has_errors())
  23. << "Generating LLVM IR from invalid SemIR::File is unsupported.";
  24. }
  25. // TODO: Move this to lower.cpp.
  26. auto FileContext::Run() -> std::unique_ptr<llvm::Module> {
  27. CARBON_CHECK(llvm_module_) << "Run can only be called once.";
  28. // Lower types.
  29. auto types = semantics_ir_->types();
  30. types_.resize_for_overwrite(types.size());
  31. for (auto [i, type] : llvm::enumerate(types)) {
  32. types_[i] = BuildType(type);
  33. }
  34. // Lower function declarations.
  35. functions_.resize_for_overwrite(semantics_ir_->functions_size());
  36. for (auto i : llvm::seq(semantics_ir_->functions_size())) {
  37. functions_[i] = BuildFunctionDeclaration(SemIR::FunctionId(i));
  38. }
  39. // TODO: Lower global variable declarations.
  40. // Lower function definitions.
  41. for (auto i : llvm::seq(semantics_ir_->functions_size())) {
  42. BuildFunctionDefinition(SemIR::FunctionId(i));
  43. }
  44. // TODO: Lower global variable initializers.
  45. return std::move(llvm_module_);
  46. }
  47. auto FileContext::BuildFunctionDeclaration(SemIR::FunctionId function_id)
  48. -> llvm::Function* {
  49. const auto& function = semantics_ir().GetFunction(function_id);
  50. const bool has_return_slot = function.return_slot_id.is_valid();
  51. auto param_refs = semantics_ir().GetNodeBlock(function.param_refs_id);
  52. SemIR::InitializingRepresentation return_rep =
  53. function.return_type_id.is_valid()
  54. ? SemIR::GetInitializingRepresentation(semantics_ir(),
  55. function.return_type_id)
  56. : SemIR::InitializingRepresentation{
  57. .kind = SemIR::InitializingRepresentation::None};
  58. CARBON_CHECK(return_rep.has_return_slot() == has_return_slot);
  59. llvm::SmallVector<llvm::Type*> param_types;
  60. // TODO: Consider either storing `param_node_ids` somewhere so that we can
  61. // reuse it from `BuildFunctionDefinition` and when building calls, or factor
  62. // out a mechanism to compute the mapping between parameters and arguments on
  63. // demand.
  64. llvm::SmallVector<SemIR::NodeId> param_node_ids;
  65. param_types.reserve(has_return_slot + param_refs.size());
  66. param_node_ids.reserve(has_return_slot + param_refs.size());
  67. if (has_return_slot) {
  68. param_types.push_back(GetType(function.return_type_id)->getPointerTo());
  69. param_node_ids.push_back(function.return_slot_id);
  70. }
  71. for (auto param_ref_id : param_refs) {
  72. auto param_type_id = semantics_ir().GetNode(param_ref_id).type_id();
  73. switch (auto value_rep =
  74. SemIR::GetValueRepresentation(semantics_ir(), param_type_id);
  75. value_rep.kind) {
  76. case SemIR::ValueRepresentation::None:
  77. break;
  78. case SemIR::ValueRepresentation::Copy:
  79. case SemIR::ValueRepresentation::Custom:
  80. param_types.push_back(GetType(value_rep.type));
  81. param_node_ids.push_back(param_ref_id);
  82. break;
  83. case SemIR::ValueRepresentation::Pointer:
  84. param_types.push_back(GetType(value_rep.type)->getPointerTo());
  85. param_node_ids.push_back(param_ref_id);
  86. break;
  87. }
  88. }
  89. // If the initializing representation doesn't produce a value, set the return
  90. // type to void.
  91. llvm::Type* return_type =
  92. return_rep.kind == SemIR::InitializingRepresentation::ByCopy
  93. ? GetType(function.return_type_id)
  94. : llvm::Type::getVoidTy(llvm_context());
  95. std::string mangled_name;
  96. if (SemIR::IsEntryPoint(semantics_ir(), function_id)) {
  97. // TODO: Add an implicit `return 0` if `Run` doesn't return `i32`.
  98. mangled_name = "main";
  99. } else {
  100. // TODO: Decide on a name mangling scheme.
  101. mangled_name = semantics_ir().GetString(function.name_id);
  102. }
  103. llvm::FunctionType* function_type =
  104. llvm::FunctionType::get(return_type, param_types, /*isVarArg=*/false);
  105. auto* llvm_function =
  106. llvm::Function::Create(function_type, llvm::Function::ExternalLinkage,
  107. mangled_name, llvm_module());
  108. // Set up parameters and the return slot.
  109. for (auto [node_id, arg] :
  110. llvm::zip_equal(param_node_ids, llvm_function->args())) {
  111. if (node_id == function.return_slot_id) {
  112. arg.setName("return");
  113. arg.addAttr(llvm::Attribute::getWithStructRetType(
  114. llvm_context(), GetType(function.return_type_id)));
  115. } else {
  116. arg.setName(semantics_ir().GetString(
  117. semantics_ir().GetNodeAs<SemIR::Parameter>(node_id).name_id));
  118. }
  119. }
  120. return llvm_function;
  121. }
  122. auto FileContext::BuildFunctionDefinition(SemIR::FunctionId function_id)
  123. -> void {
  124. const auto& function = semantics_ir().GetFunction(function_id);
  125. const auto& body_block_ids = function.body_block_ids;
  126. if (body_block_ids.empty()) {
  127. // Function is probably defined in another file; not an error.
  128. return;
  129. }
  130. llvm::Function* llvm_function = GetFunction(function_id);
  131. FunctionContext function_lowering(*this, llvm_function, vlog_stream_);
  132. const bool has_return_slot = function.return_slot_id.is_valid();
  133. // Add parameters to locals.
  134. // TODO: This duplicates the mapping between semantics nodes and LLVM
  135. // function parameters that was already computed in BuildFunctionDeclaration.
  136. // We should only do that once.
  137. auto param_refs = semantics_ir().GetNodeBlock(function.param_refs_id);
  138. int param_index = 0;
  139. if (has_return_slot) {
  140. function_lowering.SetLocal(function.return_slot_id,
  141. llvm_function->getArg(param_index));
  142. ++param_index;
  143. }
  144. for (auto param_ref_id : param_refs) {
  145. auto param_type_id = semantics_ir().GetNode(param_ref_id).type_id();
  146. if (SemIR::GetValueRepresentation(semantics_ir(), param_type_id).kind ==
  147. SemIR::ValueRepresentation::None) {
  148. function_lowering.SetLocal(
  149. param_ref_id, llvm::PoisonValue::get(GetType(param_type_id)));
  150. } else {
  151. function_lowering.SetLocal(param_ref_id,
  152. llvm_function->getArg(param_index));
  153. ++param_index;
  154. }
  155. }
  156. // Lower all blocks.
  157. for (auto block_id : body_block_ids) {
  158. CARBON_VLOG() << "Lowering " << block_id << "\n";
  159. auto* llvm_block = function_lowering.GetBlock(block_id);
  160. // Keep the LLVM blocks in lexical order.
  161. llvm_block->moveBefore(llvm_function->end());
  162. function_lowering.builder().SetInsertPoint(llvm_block);
  163. function_lowering.LowerBlock(block_id);
  164. }
  165. // LLVM requires that the entry block has no predecessors.
  166. auto* entry_block = &llvm_function->getEntryBlock();
  167. if (entry_block->hasNPredecessorsOrMore(1)) {
  168. auto* new_entry_block = llvm::BasicBlock::Create(
  169. llvm_context(), "entry", llvm_function, entry_block);
  170. llvm::BranchInst::Create(entry_block, new_entry_block);
  171. }
  172. }
  173. auto FileContext::BuildType(SemIR::NodeId node_id) -> llvm::Type* {
  174. switch (node_id.index) {
  175. case SemIR::BuiltinKind::FloatingPointType.AsInt():
  176. // TODO: Handle different sizes.
  177. return llvm::Type::getDoubleTy(*llvm_context_);
  178. case SemIR::BuiltinKind::IntegerType.AsInt():
  179. // TODO: Handle different sizes.
  180. return llvm::Type::getInt32Ty(*llvm_context_);
  181. case SemIR::BuiltinKind::BoolType.AsInt():
  182. // TODO: We may want to have different representations for `bool` storage
  183. // (`i8`) versus for `bool` values (`i1`).
  184. return llvm::Type::getInt1Ty(*llvm_context_);
  185. default:
  186. // Handled below.
  187. break;
  188. }
  189. auto node = semantics_ir_->GetNode(node_id);
  190. switch (node.kind()) {
  191. case SemIR::NodeKind::ArrayType: {
  192. auto array_type = node.As<SemIR::ArrayType>();
  193. return llvm::ArrayType::get(
  194. GetType(array_type.element_type_id),
  195. semantics_ir_->GetArrayBoundValue(array_type.bound_id));
  196. }
  197. case SemIR::NodeKind::ConstType:
  198. return GetType(node.As<SemIR::ConstType>().inner_id);
  199. case SemIR::NodeKind::PointerType:
  200. return llvm::PointerType::get(*llvm_context_, /*AddressSpace=*/0);
  201. case SemIR::NodeKind::StructType: {
  202. auto fields =
  203. semantics_ir_->GetNodeBlock(node.As<SemIR::StructType>().fields_id);
  204. llvm::SmallVector<llvm::Type*> subtypes;
  205. subtypes.reserve(fields.size());
  206. for (auto field_id : fields) {
  207. auto field = semantics_ir_->GetNodeAs<SemIR::StructTypeField>(field_id);
  208. // TODO: Handle recursive types. The restriction for builtins prevents
  209. // recursion while still letting them cache.
  210. CARBON_CHECK(field.type_id.index < SemIR::BuiltinKind::ValidCount)
  211. << field.type_id;
  212. subtypes.push_back(GetType(field.type_id));
  213. }
  214. return llvm::StructType::get(*llvm_context_, subtypes);
  215. }
  216. case SemIR::NodeKind::TupleType: {
  217. // TODO: Investigate special-casing handling of empty tuples so that they
  218. // can be collectively replaced with LLVM's void, particularly around
  219. // function returns. LLVM doesn't allow declaring variables with a void
  220. // type, so that may require significant special casing.
  221. auto elements =
  222. semantics_ir_->GetTypeBlock(node.As<SemIR::TupleType>().elements_id);
  223. llvm::SmallVector<llvm::Type*> subtypes;
  224. subtypes.reserve(elements.size());
  225. for (auto element_id : elements) {
  226. subtypes.push_back(GetType(element_id));
  227. }
  228. return llvm::StructType::get(*llvm_context_, subtypes);
  229. }
  230. default: {
  231. CARBON_FATAL() << "Cannot use node as type: " << node_id;
  232. }
  233. }
  234. }
  235. } // namespace Carbon::Lower