| // Copyright (c) 2017, 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 "bin/dfe.h" |
| #include "bin/dartutils.h" |
| #include "bin/error_exit.h" |
| #include "bin/file.h" |
| |
| #include "vm/kernel.h" |
| |
| namespace dart { |
| namespace bin { |
| |
| const char kPlatformBinaryName[] = "platform.dill"; |
| const char kVMServiceIOBinaryName[] = "vmservice_io.dill"; |
| |
| DFE::DFE() |
| : frontend_filename_(NULL), |
| platform_binary_filename_(NULL), |
| vmservice_io_binary_filename_(NULL), |
| kernel_platform_(NULL), |
| kernel_file_specified_(false) {} |
| |
| DFE::~DFE() { |
| frontend_filename_ = NULL; |
| |
| if (platform_binary_filename_ != NULL) { |
| delete platform_binary_filename_; |
| platform_binary_filename_ = NULL; |
| } |
| |
| if (kernel_platform_ != NULL) { |
| delete reinterpret_cast<kernel::Program*>(kernel_platform_); |
| kernel_platform_ = NULL; |
| } |
| } |
| |
| void DFE::SetKernelBinaries(const char* name) { |
| intptr_t len = snprintf(NULL, 0, "%s%s%s", name, File::PathSeparator(), |
| kPlatformBinaryName) + |
| 1; |
| platform_binary_filename_ = new char[len]; |
| snprintf(platform_binary_filename_, len, "%s%s%s", name, |
| File::PathSeparator(), kPlatformBinaryName); |
| |
| len = snprintf(NULL, 0, "%s%s%s", name, File::PathSeparator(), |
| kVMServiceIOBinaryName) + |
| 1; |
| vmservice_io_binary_filename_ = new char[len]; |
| snprintf(vmservice_io_binary_filename_, len, "%s%s%s", name, |
| File::PathSeparator(), kVMServiceIOBinaryName); |
| } |
| |
| Dart_Handle DFE::ReadKernelBinary(Dart_Isolate isolate, |
| const char* url_string) { |
| ASSERT(!Dart_IsServiceIsolate(isolate) && !Dart_IsKernelIsolate(isolate)); |
| // First check if the URL points to a Kernel IR file in which case we |
| // skip the compilation step and directly reload the file. |
| const uint8_t* kernel_ir = NULL; |
| intptr_t kernel_ir_size = -1; |
| if (!TryReadKernelFile(url_string, &kernel_ir, &kernel_ir_size)) { |
| // We have a source file, compile it into a kernel ir first. |
| // TODO(asiva): We will have to change this API to pass in a list of files |
| // that have changed. For now just pass in the main url_string and have it |
| // recompile the script. |
| // TODO(aam): When Frontend is ready, VM should be passing outline.dill |
| // instead of platform.dill to Frontend for compilation. |
| Dart_KernelCompilationResult kresult = |
| Dart_CompileToKernel(url_string, platform_binary_filename_); |
| if (kresult.status != Dart_KernelCompilationStatus_Ok) { |
| return Dart_NewApiError(kresult.error); |
| } |
| kernel_ir = kresult.kernel; |
| kernel_ir_size = kresult.kernel_size; |
| } |
| void* kernel_program = Dart_ReadKernelBinary(kernel_ir, kernel_ir_size); |
| ASSERT(kernel_program != NULL); |
| return Dart_NewExternalTypedData(Dart_TypedData_kUint64, kernel_program, 1); |
| } |
| |
| void* DFE::CompileAndReadScript(const char* script_uri, |
| char** error, |
| int* exit_code) { |
| // TODO(aam): When Frontend is ready, VM should be passing outline.dill |
| // instead of platform.dill to Frontend for compilation. |
| Dart_KernelCompilationResult result = |
| Dart_CompileToKernel(script_uri, platform_binary_filename_); |
| switch (result.status) { |
| case Dart_KernelCompilationStatus_Ok: |
| return Dart_ReadKernelBinary(result.kernel, result.kernel_size); |
| case Dart_KernelCompilationStatus_Error: |
| *error = result.error; // Copy error message. |
| *exit_code = kCompilationErrorExitCode; |
| break; |
| case Dart_KernelCompilationStatus_Crash: |
| *error = result.error; // Copy error message. |
| *exit_code = kDartFrontendErrorExitCode; |
| break; |
| case Dart_KernelCompilationStatus_Unknown: |
| *error = result.error; // Copy error message. |
| *exit_code = kErrorExitCode; |
| break; |
| } |
| return NULL; |
| } |
| |
| void* DFE::ReadPlatform() const { |
| return ReadScript(platform_binary_filename_); |
| } |
| |
| void* DFE::ReadVMServiceIO() const { |
| return ReadScript(vmservice_io_binary_filename_); |
| } |
| |
| void* DFE::ReadScript(const char* script_uri) const { |
| const uint8_t* buffer = NULL; |
| intptr_t buffer_length = -1; |
| bool result = TryReadKernelFile(script_uri, &buffer, &buffer_length); |
| if (result) { |
| return Dart_ReadKernelBinary(buffer, buffer_length); |
| } |
| return NULL; |
| } |
| |
| bool DFE::TryReadKernelFile(const char* script_uri, |
| const uint8_t** kernel_ir, |
| intptr_t* kernel_ir_size) const { |
| *kernel_ir = NULL; |
| *kernel_ir_size = -1; |
| void* script_file = DartUtils::OpenFile(script_uri, false); |
| if (script_file != NULL) { |
| const uint8_t* buffer = NULL; |
| DartUtils::ReadFile(&buffer, kernel_ir_size, script_file); |
| DartUtils::CloseFile(script_file); |
| if (*kernel_ir_size > 0 && buffer != NULL) { |
| if (DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size) != |
| DartUtils::kKernelMagicNumber) { |
| free(const_cast<uint8_t*>(buffer)); |
| *kernel_ir = NULL; |
| *kernel_ir_size = -1; |
| return false; |
| } else { |
| // Do not free buffer if this is a kernel file - kernel_file will be |
| // backed by the same memory as the buffer and caller will own it. |
| // Caller is responsible for freeing the buffer when this function |
| // returns true. |
| *kernel_ir = buffer; |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| } // namespace bin |
| } // namespace dart |