lowering_handle.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 "llvm/ADT/STLExtras.h"
  5. #include "llvm/ADT/Sequence.h"
  6. #include "toolchain/lowering/lowering_function_context.h"
  7. #include "toolchain/semantics/semantics_node_kind.h"
  8. namespace Carbon {
  9. auto LoweringHandleInvalid(LoweringFunctionContext& /*context*/,
  10. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  11. -> void {
  12. llvm_unreachable("never in actual IR");
  13. }
  14. auto LoweringHandleCrossReference(LoweringFunctionContext& /*context*/,
  15. SemanticsNodeId /*node_id*/,
  16. SemanticsNode node) -> void {
  17. CARBON_FATAL() << "TODO: Add support: " << node;
  18. }
  19. auto LoweringHandleAddressOf(LoweringFunctionContext& context,
  20. SemanticsNodeId node_id, SemanticsNode node)
  21. -> void {
  22. context.SetLocal(node_id, context.GetLocal(node.GetAsAddressOf()));
  23. }
  24. auto LoweringHandleArrayIndex(LoweringFunctionContext& context,
  25. SemanticsNodeId node_id, SemanticsNode node)
  26. -> void {
  27. auto [array_node_id, index_node_id] = node.GetAsArrayIndex();
  28. auto* array_value = context.GetLocal(array_node_id);
  29. auto* llvm_type =
  30. context.GetType(context.semantics_ir().GetNode(array_node_id).type_id());
  31. auto index_node = context.semantics_ir().GetNode(index_node_id);
  32. llvm::Value* array_element_value;
  33. if (index_node.kind() == SemanticsNodeKind::IntegerLiteral) {
  34. const auto index = context.semantics_ir()
  35. .GetIntegerLiteral(index_node.GetAsIntegerLiteral())
  36. .getZExtValue();
  37. array_element_value = context.GetIndexFromStructOrArray(
  38. llvm_type, array_value, index, "array.index");
  39. } else {
  40. auto* index = context.builder().CreateLoad(llvm_type->getArrayElementType(),
  41. context.GetLocal(index_node_id));
  42. // TODO: Handle return value or call such as `F()[a]`.
  43. array_element_value = context.builder().CreateInBoundsGEP(
  44. llvm_type, array_value, index, "array.index");
  45. }
  46. context.SetLocal(node_id, array_element_value);
  47. }
  48. auto LoweringHandleArrayValue(LoweringFunctionContext& context,
  49. SemanticsNodeId node_id, SemanticsNode node)
  50. -> void {
  51. auto* llvm_type = context.GetType(node.type_id());
  52. auto* alloca =
  53. context.builder().CreateAlloca(llvm_type, /*ArraySize=*/nullptr, "array");
  54. context.SetLocal(node_id, alloca);
  55. auto tuple_node_id = node.GetAsArrayValue();
  56. auto* tuple_value = context.GetLocal(tuple_node_id);
  57. auto* tuple_type =
  58. context.GetType(context.semantics_ir().GetNode(tuple_node_id).type_id());
  59. for (auto i : llvm::seq(llvm_type->getArrayNumElements())) {
  60. llvm::Value* array_element_value = context.GetIndexFromStructOrArray(
  61. tuple_type, tuple_value, i, "array.element");
  62. if (tuple_value->getType()->isPointerTy()) {
  63. array_element_value = context.builder().CreateLoad(
  64. llvm_type->getArrayElementType(), array_element_value);
  65. }
  66. // Initializing the array with values.
  67. context.builder().CreateStore(
  68. array_element_value,
  69. context.builder().CreateStructGEP(llvm_type, alloca, i));
  70. }
  71. }
  72. auto LoweringHandleAssign(LoweringFunctionContext& context,
  73. SemanticsNodeId /*node_id*/, SemanticsNode node)
  74. -> void {
  75. auto [storage_id, value_id] = node.GetAsAssign();
  76. context.builder().CreateStore(context.GetLocalLoaded(value_id),
  77. context.GetLocal(storage_id));
  78. }
  79. auto LoweringHandleBinaryOperatorAdd(LoweringFunctionContext& /*context*/,
  80. SemanticsNodeId /*node_id*/,
  81. SemanticsNode node) -> void {
  82. CARBON_FATAL() << "TODO: Add support: " << node;
  83. }
  84. auto LoweringHandleBindName(LoweringFunctionContext& /*context*/,
  85. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  86. -> void {
  87. // Probably need to do something here, but not necessary for now.
  88. }
  89. auto LoweringHandleBlockArg(LoweringFunctionContext& context,
  90. SemanticsNodeId node_id, SemanticsNode node)
  91. -> void {
  92. SemanticsNodeBlockId block_id = node.GetAsBlockArg();
  93. context.SetLocal(node_id, context.GetBlockArg(block_id, node.type_id()));
  94. }
  95. auto LoweringHandleBoolLiteral(LoweringFunctionContext& context,
  96. SemanticsNodeId node_id, SemanticsNode node)
  97. -> void {
  98. llvm::Value* v = llvm::ConstantInt::get(context.builder().getInt1Ty(),
  99. node.GetAsBoolLiteral().index);
  100. context.SetLocal(node_id, v);
  101. }
  102. auto LoweringHandleBranch(LoweringFunctionContext& context,
  103. SemanticsNodeId /*node_id*/, SemanticsNode node)
  104. -> void {
  105. SemanticsNodeBlockId target_block_id = node.GetAsBranch();
  106. // Opportunistically avoid creating a BasicBlock that contains just a branch.
  107. llvm::BasicBlock* block = context.builder().GetInsertBlock();
  108. if (block->empty() && context.TryToReuseBlock(target_block_id, block)) {
  109. // Reuse this block as the branch target.
  110. } else {
  111. context.builder().CreateBr(context.GetBlock(target_block_id));
  112. }
  113. context.builder().ClearInsertionPoint();
  114. }
  115. auto LoweringHandleBranchIf(LoweringFunctionContext& context,
  116. SemanticsNodeId /*node_id*/, SemanticsNode node)
  117. -> void {
  118. auto [target_block_id, cond_id] = node.GetAsBranchIf();
  119. llvm::Value* cond = context.GetLocalLoaded(cond_id);
  120. llvm::BasicBlock* then_block = context.GetBlock(target_block_id);
  121. llvm::BasicBlock* else_block = context.CreateSyntheticBlock();
  122. context.builder().CreateCondBr(cond, then_block, else_block);
  123. context.builder().SetInsertPoint(else_block);
  124. }
  125. auto LoweringHandleBranchWithArg(LoweringFunctionContext& context,
  126. SemanticsNodeId /*node_id*/,
  127. SemanticsNode node) -> void {
  128. auto [target_block_id, arg_id] = node.GetAsBranchWithArg();
  129. llvm::Value* arg = context.GetLocalLoaded(arg_id);
  130. SemanticsTypeId arg_type_id =
  131. context.semantics_ir().GetNode(arg_id).type_id();
  132. // Opportunistically avoid creating a BasicBlock that contains just a branch.
  133. // We only do this for a block that we know will only have a single
  134. // predecessor, so that we can correctly populate the predecessors of the
  135. // PHINode.
  136. llvm::BasicBlock* block = context.builder().GetInsertBlock();
  137. llvm::BasicBlock* phi_predecessor = block;
  138. if (block->empty() && context.IsCurrentSyntheticBlock(block) &&
  139. context.TryToReuseBlock(target_block_id, block)) {
  140. // Reuse this block as the branch target.
  141. phi_predecessor = block->getSinglePredecessor();
  142. CARBON_CHECK(phi_predecessor)
  143. << "Synthetic block did not have a single predecessor";
  144. } else {
  145. context.builder().CreateBr(context.GetBlock(target_block_id));
  146. }
  147. context.GetBlockArg(target_block_id, arg_type_id)
  148. ->addIncoming(arg, phi_predecessor);
  149. context.builder().ClearInsertionPoint();
  150. }
  151. auto LoweringHandleBuiltin(LoweringFunctionContext& /*context*/,
  152. SemanticsNodeId /*node_id*/, SemanticsNode node)
  153. -> void {
  154. CARBON_FATAL() << "TODO: Add support: " << node;
  155. }
  156. auto LoweringHandleCall(LoweringFunctionContext& context,
  157. SemanticsNodeId node_id, SemanticsNode node) -> void {
  158. auto [refs_id, function_id] = node.GetAsCall();
  159. auto* function = context.GetFunction(function_id);
  160. std::vector<llvm::Value*> args;
  161. for (auto ref_id : context.semantics_ir().GetNodeBlock(refs_id)) {
  162. args.push_back(context.GetLocalLoaded(ref_id));
  163. }
  164. if (function->getReturnType()->isVoidTy()) {
  165. context.builder().CreateCall(function, args);
  166. // TODO: use empty tuple type.
  167. // TODO: don't create the empty tuple if the call does not get assigned.
  168. context.SetLocal(node_id, context.builder().CreateAlloca(
  169. llvm::StructType::get(context.llvm_context()),
  170. /*ArraySize=*/nullptr, "call.result"));
  171. } else {
  172. context.SetLocal(node_id, context.builder().CreateCall(
  173. function, args, function->getName()));
  174. }
  175. }
  176. auto LoweringHandleDereference(LoweringFunctionContext& context,
  177. SemanticsNodeId node_id, SemanticsNode node)
  178. -> void {
  179. context.SetLocal(node_id, context.GetLocal(node.GetAsDereference()));
  180. }
  181. auto LoweringHandleFunctionDeclaration(LoweringFunctionContext& /*context*/,
  182. SemanticsNodeId /*node_id*/,
  183. SemanticsNode node) -> void {
  184. CARBON_FATAL()
  185. << "Should not be encountered. If that changes, we may want to change "
  186. "higher-level logic to skip them rather than calling this. "
  187. << node;
  188. }
  189. auto LoweringHandleIntegerLiteral(LoweringFunctionContext& context,
  190. SemanticsNodeId node_id, SemanticsNode node)
  191. -> void {
  192. llvm::APInt i =
  193. context.semantics_ir().GetIntegerLiteral(node.GetAsIntegerLiteral());
  194. // TODO: This won't offer correct semantics, but seems close enough for now.
  195. llvm::Value* v =
  196. llvm::ConstantInt::get(context.builder().getInt32Ty(), i.getSExtValue());
  197. context.SetLocal(node_id, v);
  198. }
  199. auto LoweringHandleNamespace(LoweringFunctionContext& /*context*/,
  200. SemanticsNodeId /*node_id*/,
  201. SemanticsNode /*node*/) -> void {
  202. // No action to take.
  203. }
  204. auto LoweringHandleRealLiteral(LoweringFunctionContext& context,
  205. SemanticsNodeId node_id, SemanticsNode node)
  206. -> void {
  207. SemanticsRealLiteral real =
  208. context.semantics_ir().GetRealLiteral(node.GetAsRealLiteral());
  209. // TODO: This will probably have overflow issues, and should be fixed.
  210. double val =
  211. real.mantissa.getSExtValue() *
  212. std::pow((real.is_decimal ? 10 : 2), real.exponent.getSExtValue());
  213. llvm::APFloat llvm_val(val);
  214. context.SetLocal(node_id, llvm::ConstantFP::get(
  215. context.builder().getDoubleTy(), llvm_val));
  216. }
  217. auto LoweringHandleReturn(LoweringFunctionContext& context,
  218. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  219. -> void {
  220. context.builder().CreateRetVoid();
  221. }
  222. auto LoweringHandleReturnExpression(LoweringFunctionContext& context,
  223. SemanticsNodeId /*node_id*/,
  224. SemanticsNode node) -> void {
  225. SemanticsNodeId expr_id = node.GetAsReturnExpression();
  226. context.builder().CreateRet(context.GetLocalLoaded(expr_id));
  227. }
  228. auto LoweringHandleStringLiteral(LoweringFunctionContext& /*context*/,
  229. SemanticsNodeId /*node_id*/,
  230. SemanticsNode node) -> void {
  231. CARBON_FATAL() << "TODO: Add support: " << node;
  232. }
  233. auto LoweringHandleStructAccess(LoweringFunctionContext& context,
  234. SemanticsNodeId node_id, SemanticsNode node)
  235. -> void {
  236. auto [struct_id, member_index] = node.GetAsStructAccess();
  237. auto struct_type_id = context.semantics_ir().GetNode(struct_id).type_id();
  238. auto* llvm_type = context.GetType(struct_type_id);
  239. // Get type information for member names.
  240. auto type_refs = context.semantics_ir().GetNodeBlock(
  241. context.semantics_ir()
  242. .GetNode(context.semantics_ir().GetType(struct_type_id))
  243. .GetAsStructType());
  244. auto [field_name_id, field_type_id] =
  245. context.semantics_ir()
  246. .GetNode(type_refs[member_index.index])
  247. .GetAsStructTypeField();
  248. auto member_name = context.semantics_ir().GetString(field_name_id);
  249. auto* gep = context.builder().CreateStructGEP(
  250. llvm_type, context.GetLocal(struct_id), member_index.index, member_name);
  251. context.SetLocal(node_id, gep);
  252. }
  253. auto LoweringHandleTupleIndex(LoweringFunctionContext& context,
  254. SemanticsNodeId node_id, SemanticsNode node)
  255. -> void {
  256. auto [tuple_node_id, index_node_id] = node.GetAsTupleIndex();
  257. auto* tuple_value = context.GetLocal(tuple_node_id);
  258. auto index_node = context.semantics_ir().GetNode(index_node_id);
  259. const auto index = context.semantics_ir()
  260. .GetIntegerLiteral(index_node.GetAsIntegerLiteral())
  261. .getZExtValue();
  262. auto* llvm_type =
  263. context.GetType(context.semantics_ir().GetNode(tuple_node_id).type_id());
  264. context.SetLocal(node_id, context.GetIndexFromStructOrArray(
  265. llvm_type, tuple_value, index, "tuple.index"));
  266. }
  267. auto LoweringHandleTupleValue(LoweringFunctionContext& context,
  268. SemanticsNodeId node_id, SemanticsNode node)
  269. -> void {
  270. auto* llvm_type = context.GetType(node.type_id());
  271. auto* alloca =
  272. context.builder().CreateAlloca(llvm_type, /*ArraySize=*/nullptr, "tuple");
  273. context.SetLocal(node_id, alloca);
  274. auto refs = context.semantics_ir().GetNodeBlock(node.GetAsTupleValue());
  275. for (auto [i, ref] : llvm::enumerate(refs)) {
  276. auto* gep = context.builder().CreateStructGEP(llvm_type, alloca, i);
  277. context.builder().CreateStore(context.GetLocal(ref), gep);
  278. }
  279. }
  280. auto LoweringHandleStructTypeField(LoweringFunctionContext& /*context*/,
  281. SemanticsNodeId /*node_id*/,
  282. SemanticsNode /*node*/) -> void {
  283. // No action to take.
  284. }
  285. auto LoweringHandleStructValue(LoweringFunctionContext& context,
  286. SemanticsNodeId node_id, SemanticsNode node)
  287. -> void {
  288. auto* llvm_type = context.GetType(node.type_id());
  289. auto* alloca = context.builder().CreateAlloca(
  290. llvm_type, /*ArraySize=*/nullptr, "struct");
  291. context.SetLocal(node_id, alloca);
  292. auto refs = context.semantics_ir().GetNodeBlock(node.GetAsStructValue());
  293. // Get type information for member names.
  294. auto type_refs = context.semantics_ir().GetNodeBlock(
  295. context.semantics_ir()
  296. .GetNode(context.semantics_ir().GetType(node.type_id()))
  297. .GetAsStructType());
  298. for (auto [i, ref, type_ref] : llvm::enumerate(refs, type_refs)) {
  299. auto [field_name_id, field_type_id] =
  300. context.semantics_ir().GetNode(type_ref).GetAsStructTypeField();
  301. auto member_name = context.semantics_ir().GetString(field_name_id);
  302. auto* gep =
  303. context.builder().CreateStructGEP(llvm_type, alloca, i, member_name);
  304. context.builder().CreateStore(context.GetLocal(ref), gep);
  305. }
  306. }
  307. auto LoweringHandleStubReference(LoweringFunctionContext& context,
  308. SemanticsNodeId node_id, SemanticsNode node)
  309. -> void {
  310. context.SetLocal(node_id, context.GetLocal(node.GetAsStubReference()));
  311. }
  312. auto LoweringHandleUnaryOperatorNot(LoweringFunctionContext& context,
  313. SemanticsNodeId node_id, SemanticsNode node)
  314. -> void {
  315. context.SetLocal(node_id, context.builder().CreateNot(context.GetLocal(
  316. node.GetAsUnaryOperatorNot())));
  317. }
  318. auto LoweringHandleVarStorage(LoweringFunctionContext& context,
  319. SemanticsNodeId node_id, SemanticsNode node)
  320. -> void {
  321. // TODO: Eventually this name will be optional, and we'll want to provide
  322. // something like `var` as a default. However, that's not possible right now
  323. // so cannot be tested.
  324. auto name = context.semantics_ir().GetString(node.GetAsVarStorage());
  325. auto* alloca = context.builder().CreateAlloca(context.GetType(node.type_id()),
  326. /*ArraySize=*/nullptr, name);
  327. context.SetLocal(node_id, alloca);
  328. }
  329. } // namespace Carbon