From 4ea512b4c1555c80aef8cee983418d6621594782 Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Wed, 30 Oct 2019 16:27:04 +0000 Subject: [PATCH] [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 Auto-Submit: Martin Kustermann Reviewed-by: Teagan Strickland --- runtime/llvm_codegen/codegen/BUILD.gn | 26 +++++----- runtime/llvm_codegen/codegen/custom_zone.cc | 54 +++++++++++++++++++++ runtime/llvm_codegen/codegen/custom_zone.h | 52 ++++++++++++++++++++ runtime/llvm_codegen/codegen/dart.cc | 29 +++++------ runtime/llvm_codegen/codegen/dart.h | 11 +++-- runtime/llvm_codegen/codegen/main.cc | 18 ++----- 6 files changed, 145 insertions(+), 45 deletions(-) create mode 100644 runtime/llvm_codegen/codegen/custom_zone.cc create mode 100644 runtime/llvm_codegen/codegen/custom_zone.h diff --git a/runtime/llvm_codegen/codegen/BUILD.gn b/runtime/llvm_codegen/codegen/BUILD.gn index 3addb3509fc..4ccb309ee55 100644 --- a/runtime/llvm_codegen/codegen/BUILD.gn +++ b/runtime/llvm_codegen/codegen/BUILD.gn @@ -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" ] diff --git a/runtime/llvm_codegen/codegen/custom_zone.cc b/runtime/llvm_codegen/codegen/custom_zone.cc new file mode 100644 index 00000000000..f514fe51df3 --- /dev/null +++ b/runtime/llvm_codegen/codegen/custom_zone.cc @@ -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(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 diff --git a/runtime/llvm_codegen/codegen/custom_zone.h b/runtime/llvm_codegen/codegen/custom_zone.h new file mode 100644 index 00000000000..3b3810475d3 --- /dev/null +++ b/runtime/llvm_codegen/codegen/custom_zone.h @@ -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 + +// 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 + inline ElementType* Alloc(intptr_t length) { + return static_cast( + AllocUnsafe(sizeof(ElementType) * length)); + } + + template + 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(memory); + } + + template + 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 buffers_; +}; + +} // namespace dart + +#endif // RUNTIME_LLVM_CODEGEN_CODEGEN_CUSTOM_ZONE_H_ diff --git a/runtime/llvm_codegen/codegen/dart.cc b/runtime/llvm_codegen/codegen/dart.cc index e400b41ccd9..fe219743e5a 100644 --- a/runtime/llvm_codegen/codegen/dart.cc +++ b/runtime/llvm_codegen/codegen/dart.cc @@ -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 + #include "dart.h" #include "llvm/ADT/StringSwitch.h" -#include "vm/dart_api_state.h" using namespace llvm; @@ -128,22 +129,22 @@ Expected> 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(dvalue); } void InstStaticCall::Build(BasicBlockBuilder& bb_builder) const { - // inst = (StaticCall ...) + // inst = (StaticCall ...) SmallVector 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> InstReturn::Construct( return llvm::make_unique(); } -static Expected> MakeConstants(dart::SExpList* sexpr) { - dart::ApiZone zone; +static Expected> MakeConstants(dart::Zone* zone, + dart::SExpList* sexpr) { StringMap 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 MakeBlock(dart::SExpList* sexpr, return out; } -Expected MakeFunction(dart::SExpression* sexpr, +Expected MakeFunction(dart::Zone* zone, + dart::SExpression* sexpr, const StringMap& 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 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 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); } diff --git a/runtime/llvm_codegen/codegen/dart.h b/runtime/llvm_codegen/codegen/dart.h index 1261a7bb1d8..826397ab216 100644 --- a/runtime/llvm_codegen/codegen/dart.h +++ b/runtime/llvm_codegen/codegen/dart.h @@ -7,6 +7,7 @@ #include #include +#include #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> 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> 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 MakeFunction( + dart::Zone* zone, dart::SExpression* sexpr, const llvm::StringMap& env); -#endif // RUNTIME_LLVM_CODEGEN_CODEGEN_DART_H +#endif // RUNTIME_LLVM_CODEGEN_CODEGEN_DART_H_ diff --git a/runtime/llvm_codegen/codegen/main.cc b/runtime/llvm_codegen/codegen/main.cc index 4b469bc88ee..40d8b3f47a7 100644 --- a/runtime/llvm_codegen/codegen/main.cc +++ b/runtime/llvm_codegen/codegen/main.cc @@ -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 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)