blob: 40d8b3f47a75455bd86b306f58d8b8774456ad17 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "dart.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
namespace {
StringRef tool_name;
LLVM_ATTRIBUTE_NORETURN void error(Twine message) {
WithColor::error(errs(), "llvm-codegen") << message << ".\n";
errs().flush();
exit(1);
}
LLVM_ATTRIBUTE_NORETURN void error(Error e) {
assert(e);
std::string buf;
raw_string_ostream os(buf);
logAllUnhandledErrors(std::move(e), os);
os.flush();
WithColor::error(errs(), tool_name) << buf;
exit(1);
}
LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) {
assert(EC);
error(createFileError(File, EC));
}
// We need a prelude function for printing to help get something functional
// up off the ground.
class DartPrint : public DartValue {
public:
Type* GetType(BasicBlockBuilder& bbb) const override {
auto& ctx = bbb.Context();
auto int8ty = IntegerType::getInt8Ty(ctx);
auto i8ptr = PointerType::get(int8ty, 0);
SmallVector<Type*, 1> arg_types;
arg_types.push_back(i8ptr);
return FunctionType::get(Type::getVoidTy(ctx), arg_types, false);
}
Value* Make(BasicBlockBuilder& bbb) const override {
auto ft = dyn_cast<FunctionType>(GetType(bbb));
if (ft == nullptr) return nullptr;
return Function::Create(ft, Function::ExternalLinkage, "dart:core::print",
bbb.Module());
}
};
cl::opt<std::string> sexpr_file(cl::Positional,
cl::desc("The input S-Expression file"));
cl::opt<std::string> dump_obj(
"dump-obj",
cl::desc("Specifies where to output the .o file"));
void Dump(Module* module, StringRef file, TargetMachine::CodeGenFileType type) {
legacy::PassManager pm;
std::error_code ec;
raw_fd_ostream out(file, ec);
if (ec) reportError(file, ec);
Triple target_triple{sys::getDefaultTargetTriple()};
TargetOptions options;
std::string err;
const Target* the_target =
TargetRegistry::lookupTarget(target_triple.getTriple(), err);
if (the_target == nullptr) error(err);
std::unique_ptr<TargetMachine> target(the_target->createTargetMachine(
target_triple.getTriple(), "generic", "", options, Reloc::PIC_));
if (target->addPassesToEmitFile(pm, out, nullptr, type, false))
error("couldn't add pass to emit file");
pm.run(*module);
}
} // namespace
int main(int argc, const char** argv) {
// Init llvm
InitLLVM X(argc, argv);
InitializeAllTargetInfos();
InitializeAllTargets();
InitializeAllTargetMCs();
InitializeAllAsmParsers();
InitializeAllAsmPrinters();
// Basic init
tool_name = argv[0];
cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
// Read in the file
auto file_or = MemoryBuffer::getFile(argv[1]);
if (!file_or) reportError(argv[1], file_or.getError());
std::unique_ptr<MemoryBuffer> file = std::move(file_or.get());
// Parse the file
dart::Zone zone;
dart::SExpParser parser(&zone, file->getBufferStart(), file->getBufferSize());
dart::SExpression* root = parser.Parse();
if (root == nullptr)
error(Twine("SExpParser failed: ") + parser.error_message());
// Setup our basic prelude
StringMap<const DartValue*> prelude;
DartPrint print;
prelude["dart:core::print"] = &print;
// Convert the function into an error checked format
auto function_or = MakeFunction(&zone, root, prelude);
if (!function_or) error(function_or.takeError());
auto dart_function = std::move(*function_or);
if (!dart_function.normal_entry)
error(Twine("function ") + dart_function.name + " has no normal-entry");
// Setup state for output an LLVMModule
LLVMContext context;
auto module = llvm::make_unique<Module>(argv[1], context);
auto function_type = FunctionType::get(Type::getVoidTy(context), {}, false);
auto function = Function::Create(function_type, Function::ExternalLinkage,
dart_function.name, module.get());
FunctionBuilder fb{context, *module, *function};
for (auto& bbkey : dart_function.blocks) {
auto& bb = bbkey.getValue();
auto llvmbb = fb.AddBasicBlock(bb.name);
BasicBlockBuilder bbb{llvmbb, fb};
for (auto& inst : bb.instructions) {
inst->Build(bbb);
}
}
// Dump and print the file
if (!dump_obj.empty())
Dump(module.get(), dump_obj, LLVMTargetMachine::CGFT_ObjectFile);
module->print(llvm::outs(), nullptr);
return 0;
}