handle.cpp 16 KB

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