Преглед изворни кода

Add boilerplate framework for lowering. (#2607)

This adds boilerplate for lowering; a `dump llvm-ir` command, a `lower` directory, some files to give basic structure, and a trivial test.
Jon Ross-Perkins пре 3 година
родитељ
комит
530541e56c

+ 4 - 0
bazel/testing/lit.cfg.py

@@ -46,6 +46,10 @@ def add_substitutions():
     )
 
     add_substitution("carbon", f"{run_carbon}")
+    add_substitution(
+        "carbon-run-lower",
+        f"{run_carbon} dump llvm-ir %s | {filecheck_strict}",
+    )
     add_substitution(
         "carbon-run-parser",
         f"{run_carbon} dump parse-tree %s | {filecheck_strict}",

+ 0 - 0
explorer/__init__.py


+ 2 - 0
toolchain/driver/BUILD

@@ -19,9 +19,11 @@ cc_library(
         "//toolchain/diagnostics:diagnostic_emitter",
         "//toolchain/diagnostics:sorting_diagnostic_consumer",
         "//toolchain/lexer:tokenized_buffer",
+        "//toolchain/lower",
         "//toolchain/parser:parse_tree",
         "//toolchain/semantics:semantics_ir",
         "//toolchain/source:source_buffer",
+        "@llvm-project//llvm:Core",
         "@llvm-project//llvm:Support",
     ],
 )

+ 30 - 3
toolchain/driver/driver.cpp

@@ -9,11 +9,13 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
 #include "toolchain/diagnostics/sorting_diagnostic_consumer.h"
 #include "toolchain/lexer/tokenized_buffer.h"
+#include "toolchain/lower/lower.h"
 #include "toolchain/parser/parse_tree.h"
 #include "toolchain/semantics/semantics_ir.h"
 #include "toolchain/source/source_buffer.h"
@@ -109,7 +111,13 @@ auto Driver::RunHelpSubcommand(DiagnosticConsumer& /*consumer*/,
   return true;
 }
 
-enum class DumpMode { TokenizedBuffer, ParseTree, SemanticsIR, Unknown };
+enum class DumpMode {
+  TokenizedBuffer,
+  ParseTree,
+  SemanticsIR,
+  LLVMIR,
+  Unknown
+};
 
 auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
                                llvm::ArrayRef<llvm::StringRef> args) -> bool {
@@ -122,6 +130,7 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
                        .Case("tokens", DumpMode::TokenizedBuffer)
                        .Case("parse-tree", DumpMode::ParseTree)
                        .Case("semantics-ir", DumpMode::SemanticsIR)
+                       .Case("llvm-ir", DumpMode::LLVMIR)
                        .Default(DumpMode::Unknown);
   if (dump_mode == DumpMode::Unknown) {
     error_stream_ << "ERROR: Dump mode should be one of tokens, parse-tree, or "
@@ -171,7 +180,7 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   if (dump_mode == DumpMode::TokenizedBuffer) {
     CARBON_VLOG() << "Finishing output.";
     consumer.Flush();
-    tokenized_source.Print(output_stream_);
+    output_stream_ << tokenized_source;
     return !has_errors;
   }
   CARBON_VLOG() << "tokenized_buffer: " << tokenized_source;
@@ -195,11 +204,29 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   CARBON_VLOG() << "*** SemanticsIR::MakeFromParseTree done ***\n";
   if (dump_mode == DumpMode::SemanticsIR) {
     consumer.Flush();
-    semantics_ir.Print(output_stream_);
+    output_stream_ << semantics_ir;
     return !has_errors;
   }
   CARBON_VLOG() << "semantics_ir: " << semantics_ir;
 
+  CARBON_VLOG() << "*** Lower::Make ***\n";
+  llvm::LLVMContext llvm_context;
+  const std::unique_ptr<llvm::Module> module =
+      Lower::Make(llvm_context, input_file_name, semantics_ir);
+  CARBON_VLOG() << "*** Lower::Make done ***\n";
+  if (dump_mode == DumpMode::LLVMIR) {
+    consumer.Flush();
+    module->print(output_stream_, /*AAW=*/nullptr,
+                  /*ShouldPreserveUseListOrder=*/true);
+    return !has_errors;
+  }
+  if (vlog_stream_) {
+    CARBON_VLOG() << "module: ";
+    module->print(*vlog_stream_, /*AAW=*/nullptr,
+                  /*ShouldPreserveUseListOrder=*/false,
+                  /*IsForDebug=*/true);
+  }
+
   llvm_unreachable("should handle all dump modes");
 }
 

+ 18 - 0
toolchain/lower/BUILD

@@ -0,0 +1,18 @@
+# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+    name = "lower",
+    srcs = ["lower.cpp"],
+    hdrs = ["lower.h"],
+    deps = [
+        "//common:check",
+        "//common:ostream",
+        "//toolchain/semantics:semantics_ir",
+        "@llvm-project//llvm:Core",
+        "@llvm-project//llvm:Support",
+    ],
+)

+ 0 - 0
toolchain/lower/__init__.py


+ 36 - 0
toolchain/lower/lit_autoupdate.py

@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+
+"""Updates the CHECK: lines in lit tests based on the AUTOUPDATE line."""
+
+__copyright__ = """
+Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+Exceptions. See /LICENSE for license information.
+SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+"""
+
+import os
+import sys
+from pathlib import Path
+
+
+def main() -> None:
+    # Calls the main script using execv in order to avoid Python import
+    # behaviors.
+    this_py = Path(__file__).resolve()
+    actual_py = this_py.parent.parent.parent.joinpath(
+        "bazel", "testing", "lit_autoupdate_base.py"
+    )
+    args = [
+        sys.argv[0],
+        # Flags to configure for lower testing.
+        "--tool=carbon",
+        "--autoupdate_arg=dump",
+        "--autoupdate_arg=llvm-ir",
+        "--lit_run=%{carbon-run-lower}",
+        "--testdata=toolchain/lower/testdata",
+    ] + sys.argv[1:]
+    os.execv(actual_py, args)
+
+
+if __name__ == "__main__":
+    main()

+ 16 - 0
toolchain/lower/lower.cpp

@@ -0,0 +1,16 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include "toolchain/lower/lower.h"
+
+namespace Carbon {
+
+auto Lower::Make(llvm::LLVMContext& llvm_context, llvm::StringRef module_name,
+                 const SemanticsIR& /*semantics_ir*/)
+    -> std::unique_ptr<llvm::Module> {
+  auto result = std::make_unique<llvm::Module>(module_name, llvm_context);
+  return result;
+}
+
+}  // namespace Carbon

+ 25 - 0
toolchain/lower/lower.h

@@ -0,0 +1,25 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef CARBON_TOOLCHAIN_LOWER_LOWER_H_
+#define CARBON_TOOLCHAIN_LOWER_LOWER_H_
+
+#include "common/ostream.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "toolchain/semantics/semantics_ir.h"
+
+namespace Carbon {
+
+// Lowers Semantics IR to LLVM IR.
+class Lower {
+ public:
+  static auto Make(llvm::LLVMContext& llvm_context, llvm::StringRef module_name,
+                   const SemanticsIR& semantics_ir)
+      -> std::unique_ptr<llvm::Module>;
+};
+
+}  // namespace Carbon
+
+#endif  // CARBON_TOOLCHAIN_LOWER_LOWER_H_

+ 39 - 0
toolchain/lower/testdata/BUILD

@@ -0,0 +1,39 @@
+# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+load("//bazel/sh_run:rules.bzl", "glob_sh_run")
+load("//bazel/testing:lit.bzl", "glob_lit_tests")
+
+glob_lit_tests(
+    data = [
+        "//bazel/testing:merge_output",
+        "//toolchain/driver:carbon",
+        "@llvm-project//llvm:FileCheck",
+        "@llvm-project//llvm:not",
+    ],
+    driver = "lit.cfg.py",
+    test_file_exts = ["carbon"],
+)
+
+glob_sh_run(
+    args = [
+        "$(location //toolchain/driver:carbon)",
+        "dump",
+        "llvm-ir",
+    ],
+    data = ["//toolchain/driver:carbon"],
+    file_exts = ["carbon"],
+)
+
+glob_sh_run(
+    args = [
+        "$(location //toolchain/driver:carbon)",
+        "-v",
+        "dump",
+        "llvm-ir",
+    ],
+    data = ["//toolchain/driver:carbon"],
+    file_exts = ["carbon"],
+    run_ext = "verbose",
+)

+ 8 - 0
toolchain/lower/testdata/basics/empty.carbon

@@ -0,0 +1,8 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+// RUN: %{carbon-run-lower}
+// CHECK:STDOUT: ; ModuleID = '{{.*}}/toolchain/lower/testdata/basics/empty.carbon'
+// CHECK:STDOUT: source_filename = "{{.*}}/toolchain/lower/testdata/basics/empty.carbon"

+ 1 - 0
toolchain/lower/testdata/lit.cfg.py

@@ -0,0 +1 @@
+../../../bazel/testing/lit.cfg.py