Codegen: Given a carbon file prints the assembly to the stdout (#2944)

Co-authored-by: Farzana Ahmed Siddique <fasiddique@google.com>
This commit is contained in:
Farzana Ahmed Siddique
2023-06-23 15:23:39 -07:00
committed by GitHub
co-authored by Farzana Ahmed Siddique
parent b908c6e274
commit aad4ed2083
7 changed files with 148 additions and 1 deletions
+20
View File
@@ -0,0 +1,20 @@
# 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 = "codegen",
srcs = ["codegen.cpp"],
hdrs = ["codegen.h"],
deps = [
"@llvm-project//llvm:AllTargetsAsmParsers",
"@llvm-project//llvm:AllTargetsCodeGens",
"@llvm-project//llvm:Core",
"@llvm-project//llvm:MC",
"@llvm-project//llvm:Support",
"@llvm-project//llvm:Target",
"@llvm-project//llvm:TargetParser",
],
)
+71
View File
@@ -0,0 +1,71 @@
// 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/codegen/codegen.h"
#include <cstdio>
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/Host.h"
namespace Carbon {
auto PrintAssemblyFromModule(llvm::Module& module,
llvm::StringRef target_triple,
llvm::raw_pwrite_stream& error_stream,
llvm::raw_pwrite_stream& output_stream) -> bool {
// Initialize the target registry etc.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllAsmPrinters();
std::string error;
llvm::StringRef triple = target_triple;
std::string host_triple;
if (target_triple.empty()) {
host_triple = llvm::sys::getDefaultTargetTriple();
triple = host_triple;
}
const auto* target = llvm::TargetRegistry::lookupTarget(triple, error);
if (!target) {
error_stream << "ERROR: " << error << "\n";
return false;
}
constexpr llvm::StringLiteral CPU = "generic";
constexpr llvm::StringLiteral Features = "";
llvm::TargetOptions target_opts;
std::optional<llvm::Reloc::Model> reloc_model;
auto* target_machine = target->createTargetMachine(
target_triple, CPU, Features, target_opts, reloc_model);
module.setDataLayout(target_machine->createDataLayout());
module.setTargetTriple(target_triple);
// Using the legacy PM to generate the assembly since the new PM
// does not work with this yet.
// TODO: make the new PM work with the codegen pipeline.
llvm::legacy::PassManager pass;
auto file_type = llvm::CGFT_AssemblyFile;
if (target_machine->addPassesToEmitFile(pass, output_stream, nullptr,
file_type)) {
error_stream << "Nothing to write to object file\n";
return false;
}
pass.run(module);
delete target_machine;
return true;
}
} // namespace Carbon
+22
View File
@@ -0,0 +1,22 @@
// 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_CODEGEN_CODEGEN_H_
#define CARBON_TOOLCHAIN_CODEGEN_CODEGEN_H_
#include <cstdint>
#include "llvm/IR/Module.h"
namespace Carbon {
// Prints the assembly to stdout for the given llvm module.
// If print fails, this returns false and any information about the failure is
// printed to the error stream.
auto PrintAssemblyFromModule(llvm::Module& module,
llvm::StringRef target_triple,
llvm::raw_pwrite_stream& error_stream,
llvm::raw_pwrite_stream& output_stream) -> bool;
} // namespace Carbon
#endif // CARBON_TOOLCHAIN_CODEGEN_CODEGEN_H_
+1
View File
@@ -14,6 +14,7 @@ cc_library(
textual_hdrs = ["flags.def"],
deps = [
"//common:vlog",
"//toolchain/codegen",
"//toolchain/diagnostics:diagnostic_emitter",
"//toolchain/diagnostics:sorting_diagnostic_consumer",
"//toolchain/lexer:tokenized_buffer",
+18 -1
View File
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Format.h"
#include "toolchain/codegen/codegen.h"
#include "toolchain/diagnostics/diagnostic_emitter.h"
#include "toolchain/diagnostics/sorting_diagnostic_consumer.h"
#include "toolchain/lexer/tokenized_buffer.h"
@@ -116,6 +117,7 @@ enum class DumpMode {
ParseTree,
SemanticsIR,
LLVMIR,
Assembly,
Unknown
};
@@ -131,10 +133,11 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
.Case("parse-tree", DumpMode::ParseTree)
.Case("semantics-ir", DumpMode::SemanticsIR)
.Case("llvm-ir", DumpMode::LLVMIR)
.Case("assembly", DumpMode::Assembly)
.Default(DumpMode::Unknown);
if (dump_mode == DumpMode::Unknown) {
error_stream_ << "ERROR: Dump mode should be one of tokens, parse-tree, "
"semantics-ir, or llvm-ir.\n";
"semantics-ir, llvm-ir, or assembly.\n";
return false;
}
args = args.drop_front();
@@ -153,6 +156,13 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
semantics_ir_include_builtins = true;
}
llvm::StringRef target_triple;
if (dump_mode == DumpMode::Assembly && !args.empty() &&
args.front().starts_with("--target_triple=")) {
target_triple = args.front().split("=").second;
args = args.drop_front();
}
if (args.empty()) {
error_stream_ << "ERROR: No input file specified.\n";
return false;
@@ -236,6 +246,13 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
/*IsForDebug=*/true);
}
if (dump_mode == DumpMode::Assembly) {
consumer.Flush();
has_errors |= !Carbon::PrintAssemblyFromModule(
*module, target_triple, error_stream_, output_stream_);
return !has_errors;
}
llvm_unreachable("should handle all dump modes");
}
+8
View File
@@ -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
//
// RUN: %{carbon} dump assembly --target_triple=x86_64-unknown-linux-gnu %s | %{FileCheck-allow-unmatched}
// CHECK:STDOUT: Main:
fn Main() -> i32 { return 0; }
@@ -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
//
// RUN: %{not} %{carbon} dump assembly --target_triple=x86_687-unknown-linux-gnu %s | %{FileCheck-strict}
// CHECK:STDERR: ERROR: {{.*}}
fn Main() -> i32 { return 0; }