lowering_handle.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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_context.h"
  5. namespace Carbon {
  6. auto LoweringHandleInvalid(LoweringContext& /*context*/,
  7. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  8. -> void {
  9. llvm_unreachable("never in actual IR");
  10. }
  11. auto LoweringHandleCrossReference(LoweringContext& /*context*/,
  12. SemanticsNodeId /*node_id*/,
  13. SemanticsNode node) -> void {
  14. CARBON_FATAL() << "TODO: Add support: " << node;
  15. }
  16. auto LoweringHandleAssign(LoweringContext& context, SemanticsNodeId /*node_id*/,
  17. SemanticsNode node) -> void {
  18. auto [storage_id, value_id] = node.GetAsAssign();
  19. context.builder().CreateStore(context.GetLocalLoaded(value_id),
  20. context.GetLocal(storage_id));
  21. }
  22. auto LoweringHandleBinaryOperatorAdd(LoweringContext& /*context*/,
  23. SemanticsNodeId /*node_id*/,
  24. SemanticsNode node) -> void {
  25. CARBON_FATAL() << "TODO: Add support: " << node;
  26. }
  27. auto LoweringHandleBindName(LoweringContext& /*context*/,
  28. SemanticsNodeId /*node_id*/, SemanticsNode /*node*/)
  29. -> void {
  30. // Probably need to do something here, but not necessary for now.
  31. }
  32. auto LoweringHandleBlockArg(LoweringContext& /*context*/,
  33. SemanticsNodeId /*node_id*/, SemanticsNode node)
  34. -> void {
  35. CARBON_FATAL() << "TODO: Add support: " << node;
  36. }
  37. auto LoweringHandleBoolLiteral(LoweringContext& context,
  38. SemanticsNodeId node_id, SemanticsNode node)
  39. -> void {
  40. llvm::Value* v = llvm::ConstantInt::get(context.builder().getInt1Ty(),
  41. node.GetAsBoolLiteral().index);
  42. context.SetLocal(node_id, v);
  43. }
  44. auto LoweringHandleBranch(LoweringContext& /*context*/,
  45. SemanticsNodeId /*node_id*/, SemanticsNode node)
  46. -> void {
  47. CARBON_FATAL() << "TODO: Add support: " << node;
  48. }
  49. auto LoweringHandleBranchIf(LoweringContext& /*context*/,
  50. SemanticsNodeId /*node_id*/, SemanticsNode node)
  51. -> void {
  52. CARBON_FATAL() << "TODO: Add support: " << node;
  53. }
  54. auto LoweringHandleBranchWithArg(LoweringContext& /*context*/,
  55. SemanticsNodeId /*node_id*/,
  56. SemanticsNode node) -> void {
  57. CARBON_FATAL() << "TODO: Add support: " << node;
  58. }
  59. auto LoweringHandleBuiltin(LoweringContext& /*context*/,
  60. SemanticsNodeId /*node_id*/, SemanticsNode node)
  61. -> void {
  62. CARBON_FATAL() << "TODO: Add support: " << node;
  63. }
  64. auto LoweringHandleCall(LoweringContext& context, SemanticsNodeId node_id,
  65. SemanticsNode node) -> void {
  66. auto [refs_id, function_id] = node.GetAsCall();
  67. auto* function = context.GetFunction(function_id);
  68. std::vector<llvm::Value*> args;
  69. for (auto ref_id : context.semantics_ir().GetNodeBlock(refs_id)) {
  70. args.push_back(context.GetLocalLoaded(ref_id));
  71. }
  72. auto* value =
  73. context.builder().CreateCall(function, args, function->getName());
  74. context.SetLocal(node_id, value);
  75. }
  76. auto LoweringHandleCodeBlock(LoweringContext& /*context*/,
  77. SemanticsNodeId /*node_id*/, SemanticsNode node)
  78. -> void {
  79. CARBON_FATAL() << "TODO: Add support: " << node;
  80. }
  81. auto LoweringHandleFunctionDeclaration(LoweringContext& /*context*/,
  82. SemanticsNodeId /*node_id*/,
  83. SemanticsNode node) -> void {
  84. CARBON_FATAL()
  85. << "Should not be encountered. If that changes, we may want to change "
  86. "higher-level logic to skip them rather than calling this. "
  87. << node;
  88. }
  89. auto LoweringHandleIntegerLiteral(LoweringContext& context,
  90. SemanticsNodeId node_id, SemanticsNode node)
  91. -> void {
  92. llvm::APInt i =
  93. context.semantics_ir().GetIntegerLiteral(node.GetAsIntegerLiteral());
  94. // TODO: This won't offer correct semantics, but seems close enough for now.
  95. llvm::Value* v =
  96. llvm::ConstantInt::get(context.builder().getInt32Ty(), i.getSExtValue());
  97. context.SetLocal(node_id, v);
  98. }
  99. auto LoweringHandleRealLiteral(LoweringContext& context,
  100. SemanticsNodeId node_id, SemanticsNode node)
  101. -> void {
  102. SemanticsRealLiteral real =
  103. context.semantics_ir().GetRealLiteral(node.GetAsRealLiteral());
  104. // TODO: This will probably have overflow issues, and should be fixed.
  105. double val =
  106. real.mantissa.getSExtValue() *
  107. std::pow((real.is_decimal ? 10 : 2), real.exponent.getSExtValue());
  108. llvm::APFloat llvm_val(val);
  109. context.SetLocal(node_id, llvm::ConstantFP::get(
  110. context.builder().getDoubleTy(), llvm_val));
  111. }
  112. auto LoweringHandleReturn(LoweringContext& context, SemanticsNodeId /*node_id*/,
  113. SemanticsNode /*node*/) -> void {
  114. context.builder().CreateRetVoid();
  115. }
  116. auto LoweringHandleReturnExpression(LoweringContext& context,
  117. SemanticsNodeId /*node_id*/,
  118. SemanticsNode node) -> void {
  119. SemanticsNodeId expr_id = node.GetAsReturnExpression();
  120. context.builder().CreateRet(context.GetLocalLoaded(expr_id));
  121. }
  122. auto LoweringHandleStringLiteral(LoweringContext& /*context*/,
  123. SemanticsNodeId /*node_id*/,
  124. SemanticsNode node) -> void {
  125. CARBON_FATAL() << "TODO: Add support: " << node;
  126. }
  127. auto LoweringHandleStructMemberAccess(LoweringContext& context,
  128. SemanticsNodeId node_id,
  129. SemanticsNode node) -> void {
  130. auto [struct_id, member_index] = node.GetAsStructMemberAccess();
  131. auto struct_type_id = context.semantics_ir().GetNode(struct_id).type_id();
  132. auto* llvm_type = context.GetType(struct_type_id);
  133. // Get type information for member names.
  134. auto type_refs = context.semantics_ir().GetNodeBlock(
  135. context.semantics_ir()
  136. .GetNode(context.semantics_ir().GetType(struct_type_id))
  137. .GetAsStructType());
  138. auto member_name = context.semantics_ir().GetString(
  139. context.semantics_ir()
  140. .GetNode(type_refs[member_index.index])
  141. .GetAsStructTypeField());
  142. auto* gep = context.builder().CreateStructGEP(
  143. llvm_type, context.GetLocal(struct_id), member_index.index, member_name);
  144. context.SetLocal(node_id, gep);
  145. }
  146. auto LoweringHandleStructType(LoweringContext& /*context*/,
  147. SemanticsNodeId /*node_id*/,
  148. SemanticsNode /*node*/) -> void {
  149. // No action to take.
  150. }
  151. auto LoweringHandleStructTypeField(LoweringContext& /*context*/,
  152. SemanticsNodeId /*node_id*/,
  153. SemanticsNode /*node*/) -> void {
  154. // No action to take.
  155. }
  156. auto LoweringHandleStructValue(LoweringContext& context,
  157. SemanticsNodeId node_id, SemanticsNode node)
  158. -> void {
  159. auto* llvm_type = context.GetType(node.type_id());
  160. auto* alloca = context.builder().CreateAlloca(
  161. llvm_type, /*ArraySize=*/nullptr, "StructLiteralValue");
  162. context.SetLocal(node_id, alloca);
  163. auto refs = context.semantics_ir().GetNodeBlock(node.GetAsStructValue());
  164. // Get type information for member names.
  165. auto type_refs = context.semantics_ir().GetNodeBlock(
  166. context.semantics_ir()
  167. .GetNode(context.semantics_ir().GetType(node.type_id()))
  168. .GetAsStructType());
  169. for (int i = 0; i < static_cast<int>(refs.size()); ++i) {
  170. auto member_name = context.semantics_ir().GetString(
  171. context.semantics_ir().GetNode(type_refs[i]).GetAsStructTypeField());
  172. auto* gep =
  173. context.builder().CreateStructGEP(llvm_type, alloca, i, member_name);
  174. context.builder().CreateStore(context.GetLocal(refs[i]), gep);
  175. }
  176. }
  177. auto LoweringHandleStubReference(LoweringContext& context,
  178. SemanticsNodeId node_id, SemanticsNode node)
  179. -> void {
  180. context.SetLocal(node_id, context.GetLocal(node.GetAsStubReference()));
  181. }
  182. auto LoweringHandleVarStorage(LoweringContext& context, SemanticsNodeId node_id,
  183. SemanticsNode node) -> void {
  184. // TODO: This should provide a name, not just `var`. Also, LLVM requires
  185. // globals to have a name. Do we want to generate a name, which would need to
  186. // be consistent across translation units, or use the given name, which
  187. // requires either looking ahead for BindName or restructuring semantics,
  188. // either of which affects the destructuring due to the difference in
  189. // storage?
  190. auto* alloca = context.builder().CreateAlloca(context.GetType(node.type_id()),
  191. /*ArraySize=*/nullptr, "var");
  192. context.SetLocal(node_id, alloca);
  193. }
  194. } // namespace Carbon