lowering_handle.cpp 13 KB

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