mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[llvm_codegen] Use exclusively SExpression support from VM and nothing else.
The LLVM code generator should only consume the serialized IR and not use any other VM functionality. This CL adds a custom zone which can be used for the deserialized IR nodes and removes any Dart_SetVMFlags/Dart_Initialize/ApiZone/... calls. This works with the existing example: % ninja -C out/ReleaseX64 codegen % out/ReleaseX64/codegen runtime/llvm_codegen/test/codegen/Inputs/hello.sex ... define void @"hello.dart::main"() { B1: %0 = call i8* @llvm.stacksave() %1 = ptrtoint i8* %0 to i64 %2 = load i64, i64 addrspace(256)* inttoptr (i64 72 to i64 addrspace(256)*) %3 = icmp ult i64 %1, %2 br i1 %3, label %4, label %5 ... ret void } ... Change-Id: I1d07ba6bc122d100c73f97cfa961d36240489666 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120792 Commit-Queue: Martin Kustermann <kustermann@google.com> Auto-Submit: Martin Kustermann <kustermann@google.com> Reviewed-by: Teagan Strickland <sstrickl@google.com>
This commit is contained in:
parent
cb2f45ea6b
commit
4ea512b4c1
|
@ -5,13 +5,9 @@
|
|||
import("../../vm/compiler/compiler_sources.gni")
|
||||
|
||||
config("config") {
|
||||
include_dirs = [
|
||||
"../../"
|
||||
]
|
||||
include_dirs = [ "../../" ]
|
||||
|
||||
cflags = [
|
||||
"-Wno-unused-private-field"
|
||||
]
|
||||
cflags = [ "-Wno-unused-private-field" ]
|
||||
}
|
||||
|
||||
_lib_llvm_so = "../../../third_party/llvm/lib/libLLVM-9svn.so"
|
||||
|
@ -22,23 +18,27 @@ config("llvm") {
|
|||
}
|
||||
|
||||
copy("lib_llvm") {
|
||||
sources = [ _lib_llvm_so ]
|
||||
outputs = [ "$root_out_dir/libLLVM-9svn.so" ]
|
||||
sources = [
|
||||
_lib_llvm_so,
|
||||
]
|
||||
outputs = [
|
||||
"$root_out_dir/libLLVM-9svn.so",
|
||||
]
|
||||
public_configs = [ ":llvm" ]
|
||||
}
|
||||
|
||||
executable("codegen") {
|
||||
sources = [
|
||||
"main.cc",
|
||||
"custom_zone.cc",
|
||||
"custom_zone.h",
|
||||
"dart.cc",
|
||||
"dart.h"
|
||||
"dart.h",
|
||||
"main.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":lib_llvm",
|
||||
"../..:libdart_nosnapshot_with_precompiler",
|
||||
"../../vm:libdart_vm_nosnapshot_with_precompiler",
|
||||
"../../platform:libdart_platform_nosnapshot_with_precompiler",
|
||||
"../../third_party/double-conversion/src:libdouble_conversion",
|
||||
]
|
||||
|
||||
configs += [ ":config" ]
|
||||
|
|
54
runtime/llvm_codegen/codegen/custom_zone.cc
Normal file
54
runtime/llvm_codegen/codegen/custom_zone.cc
Normal file
|
@ -0,0 +1,54 @@
|
|||
// 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 "custom_zone.h"
|
||||
|
||||
#include "platform/text_buffer.h"
|
||||
#include "platform/unicode.h"
|
||||
#include "platform/utils.h"
|
||||
#include "vm/double_conversion.h"
|
||||
#include "vm/os.h"
|
||||
|
||||
#include "platform/assert.cc" // NOLINT
|
||||
#include "platform/syslog_linux.cc" // NOLINT
|
||||
#include "platform/text_buffer.cc" // NOLINT
|
||||
#include "platform/unicode.cc" // NOLINT
|
||||
#include "platform/utils.cc" // NOLINT
|
||||
#include "platform/utils_linux.cc" // NOLINT
|
||||
#include "vm/compiler/backend/sexpression.cc" // NOLINT
|
||||
#include "vm/double_conversion.cc" // NOLINT
|
||||
#include "vm/flags.cc" // NOLINT
|
||||
#include "vm/os_linux.cc" // NOLINT
|
||||
#include "vm/zone_text_buffer.cc" // NOLINT
|
||||
|
||||
namespace dart {
|
||||
|
||||
void* ZoneAllocated::operator new(uintptr_t size, dart::Zone* zone) {
|
||||
return reinterpret_cast<void*>(zone->AllocUnsafe(size));
|
||||
}
|
||||
|
||||
Zone::~Zone() {
|
||||
while (buffers_.size() > 0) {
|
||||
free(buffers_.back());
|
||||
buffers_.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void* Zone::AllocUnsafe(intptr_t size) {
|
||||
void* memory = malloc(size);
|
||||
buffers_.push_back(memory);
|
||||
return memory;
|
||||
}
|
||||
|
||||
DART_EXPORT void Dart_PrepareToAbort() {
|
||||
fprintf(stderr, "Dart_PrepareToAbort() not implemented!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DART_EXPORT void Dart_DumpNativeStackTrace(void* context) {
|
||||
fprintf(stderr, "Dart_DumpNativeStackTrace() not implemented!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
} // namespace dart
|
52
runtime/llvm_codegen/codegen/custom_zone.h
Normal file
52
runtime/llvm_codegen/codegen/custom_zone.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
// 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.
|
||||
|
||||
#ifndef RUNTIME_LLVM_CODEGEN_CODEGEN_CUSTOM_ZONE_H_
|
||||
#define RUNTIME_LLVM_CODEGEN_CODEGEN_CUSTOM_ZONE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
// We use a custom zone here which doesn't depend on VM internals (e.g. handles,
|
||||
// thread, ...)
|
||||
#if defined(RUNTIME_VM_ZONE_H_)
|
||||
#error "We want our own zone implementation"
|
||||
#endif
|
||||
#define RUNTIME_VM_ZONE_H_
|
||||
|
||||
namespace dart {
|
||||
|
||||
class Zone {
|
||||
public:
|
||||
Zone() {}
|
||||
~Zone();
|
||||
|
||||
template <class ElementType>
|
||||
inline ElementType* Alloc(intptr_t length) {
|
||||
return static_cast<ElementType*>(
|
||||
AllocUnsafe(sizeof(ElementType) * length));
|
||||
}
|
||||
|
||||
template <class ElementType>
|
||||
inline ElementType* Realloc(ElementType* old_array,
|
||||
intptr_t old_length,
|
||||
intptr_t new_length) {
|
||||
void* memory = AllocUnsafe(sizeof(ElementType) * new_length);
|
||||
memmove(memory, old_array, sizeof(ElementType) * old_length);
|
||||
return static_cast<ElementType*>(memory);
|
||||
}
|
||||
|
||||
template <class ElementType>
|
||||
void Free(ElementType* old_array, intptr_t len) {}
|
||||
|
||||
void* AllocUnsafe(intptr_t size);
|
||||
|
||||
private:
|
||||
Zone(const Zone&) = delete;
|
||||
void operator=(const Zone&) = delete;
|
||||
std::vector<void*> buffers_;
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // RUNTIME_LLVM_CODEGEN_CODEGEN_CUSTOM_ZONE_H_
|
|
@ -2,10 +2,11 @@
|
|||
// 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 <utility>
|
||||
|
||||
#include "dart.h"
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "vm/dart_api_state.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -128,22 +129,22 @@ Expected<std::unique_ptr<DartInstruction>> InstPushArgument::Construct(
|
|||
return CreateError("PushArgument should have exactly 1 argument");
|
||||
}
|
||||
dart::SExpSymbol* arg = inst->At(1)->AsSymbol();
|
||||
if (!arg) {
|
||||
if (arg == nullptr) {
|
||||
return CreateError("Expected PushArgument's argument to be a symbol");
|
||||
}
|
||||
const DartValue* dvalue = bb_builder.GetDef(arg->value());
|
||||
if (!dvalue) {
|
||||
if (dvalue == nullptr) {
|
||||
return CreateError(Twine(arg->value()) + " is not a valid symbol");
|
||||
}
|
||||
return llvm::make_unique<InstPushArgument>(dvalue);
|
||||
}
|
||||
|
||||
void InstStaticCall::Build(BasicBlockBuilder& bb_builder) const {
|
||||
// inst = (StaticCall <function-symbol> <arg> ...)
|
||||
// inst = (StaticCall <function-symbol> <arg> ...)
|
||||
|
||||
SmallVector<Value*, 8> args;
|
||||
size_t arg_count = args_len_;
|
||||
while (arg_count) {
|
||||
while (arg_count > 0) {
|
||||
arg_count--;
|
||||
args.push_back(bb_builder.PopArgument());
|
||||
}
|
||||
|
@ -196,15 +197,15 @@ Expected<std::unique_ptr<DartInstruction>> InstReturn::Construct(
|
|||
return llvm::make_unique<InstReturn>();
|
||||
}
|
||||
|
||||
static Expected<StringMap<DartConstant>> MakeConstants(dart::SExpList* sexpr) {
|
||||
dart::ApiZone zone;
|
||||
static Expected<StringMap<DartConstant>> MakeConstants(dart::Zone* zone,
|
||||
dart::SExpList* sexpr) {
|
||||
StringMap<DartConstant> out;
|
||||
for (intptr_t i = 1; i < sexpr->Length(); ++i) {
|
||||
DartConstant constant;
|
||||
dart::SExpList* def = sexpr->At(i)->AsList();
|
||||
if (!def) {
|
||||
return CreateError(Twine("Stray token in constants at location ") +
|
||||
Twine(i) + sexpr->At(i)->ToCString(zone.GetZone()));
|
||||
Twine(i) + sexpr->At(i)->ToCString(zone));
|
||||
}
|
||||
if (def->Length() != 3) {
|
||||
return CreateError("Constant definitions must have exactly 3 lines");
|
||||
|
@ -287,10 +288,10 @@ static Expected<DartBlock> MakeBlock(dart::SExpList* sexpr,
|
|||
return out;
|
||||
}
|
||||
|
||||
Expected<DartFunction> MakeFunction(dart::SExpression* sexpr,
|
||||
Expected<DartFunction> MakeFunction(dart::Zone* zone,
|
||||
dart::SExpression* sexpr,
|
||||
const StringMap<const DartValue*>& env) {
|
||||
// Basic checking that this s-expression looks like a function
|
||||
dart::ApiZone zone;
|
||||
dart::SExpList* flist = sexpr->AsList();
|
||||
if (!flist) return CreateError("S-Expression was not a function list");
|
||||
if (flist->Length() < 2)
|
||||
|
@ -312,10 +313,10 @@ Expected<DartFunction> MakeFunction(dart::SExpression* sexpr,
|
|||
for (intptr_t i = 2; i < flist->Length(); ++i) {
|
||||
dart::SExpList* chunk = flist->At(i)->AsList();
|
||||
// Everything is a list so far so error out on other options
|
||||
if (!chunk)
|
||||
if (!chunk) {
|
||||
return CreateError(Twine("Stray token in function at location ") +
|
||||
Twine(i) + ": " +
|
||||
flist->At(i)->ToCString(zone.GetZone()));
|
||||
Twine(i) + ": " + flist->At(i)->ToCString(zone));
|
||||
}
|
||||
dart::SExpSymbol* chunk_symbol = chunk->At(0)->AsSymbol();
|
||||
if (!chunk_symbol)
|
||||
return CreateError(Twine("Expected element ") + Twine(i) +
|
||||
|
@ -323,7 +324,7 @@ Expected<DartFunction> MakeFunction(dart::SExpression* sexpr,
|
|||
StringRef chunk_tag = chunk_symbol->value();
|
||||
|
||||
if (chunk_tag == "constants") {
|
||||
auto constants = MakeConstants(chunk);
|
||||
auto constants = MakeConstants(zone, chunk);
|
||||
if (!constants) return constants.takeError();
|
||||
function.constants = std::move(*constants);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
|
@ -14,6 +15,9 @@
|
|||
#include "llvm/IR/ValueSymbolTable.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/WithColor.h"
|
||||
|
||||
// Ensure to use our own zone.
|
||||
#include "custom_zone.h"
|
||||
#include "vm/compiler/backend/sexpression.h"
|
||||
|
||||
// This file introduces several representations that exist between
|
||||
|
@ -229,7 +233,7 @@ class DartInstruction {
|
|||
// an instance of a CheckStackOverflow instruction.
|
||||
class InstCheckStackOverflow : public DartInstruction {
|
||||
public:
|
||||
explicit InstCheckStackOverflow() {}
|
||||
InstCheckStackOverflow() {}
|
||||
~InstCheckStackOverflow() override {}
|
||||
void Build(BasicBlockBuilder& bb_builder) const override;
|
||||
static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
|
||||
|
@ -273,7 +277,7 @@ class InstStaticCall : public DartInstruction {
|
|||
// instruction.
|
||||
class InstReturn : public DartInstruction {
|
||||
public:
|
||||
explicit InstReturn() {}
|
||||
InstReturn() {}
|
||||
~InstReturn() override {}
|
||||
void Build(BasicBlockBuilder& bb_builder) const override;
|
||||
static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
|
||||
|
@ -303,7 +307,8 @@ struct DartFunction {
|
|||
// of the S-Expression is invalid then the llvm::Expected will hold an
|
||||
// error explaining the issue.
|
||||
llvm::Expected<DartFunction> MakeFunction(
|
||||
dart::Zone* zone,
|
||||
dart::SExpression* sexpr,
|
||||
const llvm::StringMap<const DartValue*>& env);
|
||||
|
||||
#endif // RUNTIME_LLVM_CODEGEN_CODEGEN_DART_H
|
||||
#endif // RUNTIME_LLVM_CODEGEN_CODEGEN_DART_H_
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
#include "vm/dart_api_state.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
@ -102,24 +100,14 @@ int main(int argc, const char** argv) {
|
|||
tool_name = argv[0];
|
||||
cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
|
||||
|
||||
// Init dart
|
||||
const char* err = Dart_SetVMFlags(0, argv + 2);
|
||||
if (err != nullptr) error(Twine("Dart_SetVMFlags failed: ") + err);
|
||||
Dart_InitializeParams init_params;
|
||||
memset(&init_params, 0, sizeof(init_params));
|
||||
init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
err = Dart_Initialize(&init_params);
|
||||
if (err != nullptr) error(Twine("Dart Initialization failed: ") + err);
|
||||
|
||||
// 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::ApiZone zone;
|
||||
dart::SExpParser parser(zone.GetZone(), file->getBufferStart(),
|
||||
file->getBufferSize());
|
||||
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());
|
||||
|
@ -130,7 +118,7 @@ int main(int argc, const char** argv) {
|
|||
prelude["dart:core::print"] = &print;
|
||||
|
||||
// Convert the function into an error checked format
|
||||
auto function_or = MakeFunction(root, prelude);
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue