6fe15f6df9
This works around bugs in UndefinedBehaviorSanitizer and Clang. Bug: b/28638298 Change-Id: I6be595f9664516019d28017d24559583a1ae3a21 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144354 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
72 lines
2.8 KiB
C++
72 lines
2.8 KiB
C++
// Copyright (c) 2020, 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 "vm/compiler/ffi/callback.h"
|
|
|
|
#include "vm/symbols.h"
|
|
|
|
namespace dart {
|
|
|
|
namespace compiler {
|
|
|
|
namespace ffi {
|
|
|
|
FunctionPtr NativeCallbackFunction(const Function& c_signature,
|
|
const Function& dart_target,
|
|
const Instance& exceptional_return) {
|
|
Thread* const thread = Thread::Current();
|
|
const int32_t callback_id = thread->AllocateFfiCallbackId();
|
|
|
|
// Create a new Function named '<target>_FfiCallback' and stick it in the
|
|
// 'dart:ffi' library. Note that these functions will never be invoked by
|
|
// Dart, so they have may have duplicate names.
|
|
Zone* const zone = thread->zone();
|
|
const auto& name = String::Handle(
|
|
zone, Symbols::FromConcat(thread, Symbols::FfiCallback(),
|
|
String::Handle(zone, dart_target.name())));
|
|
const Library& lib = Library::Handle(zone, Library::FfiLibrary());
|
|
const Class& owner_class = Class::Handle(zone, lib.toplevel_class());
|
|
const Function& function =
|
|
Function::Handle(zone, Function::New(name, FunctionLayout::kFfiTrampoline,
|
|
/*is_static=*/true,
|
|
/*is_const=*/false,
|
|
/*is_abstract=*/false,
|
|
/*is_external=*/false,
|
|
/*is_native=*/false, owner_class,
|
|
TokenPosition::kNoSource));
|
|
function.set_is_debuggable(false);
|
|
|
|
// Set callback-specific fields which the flow-graph builder needs to generate
|
|
// the body.
|
|
function.SetFfiCSignature(c_signature);
|
|
function.SetFfiCallbackId(callback_id);
|
|
function.SetFfiCallbackTarget(dart_target);
|
|
|
|
// We need to load the exceptional return value as a constant in the generated
|
|
// function. Even though the FE ensures that it is a constant, it could still
|
|
// be a literal allocated in new space. We need to copy it into old space in
|
|
// that case.
|
|
//
|
|
// Exceptional return values currently cannot be pointers because we don't
|
|
// have constant pointers.
|
|
//
|
|
// TODO(36730): We'll need to extend this when we support passing/returning
|
|
// structs by value.
|
|
ASSERT(exceptional_return.IsNull() || exceptional_return.IsNumber());
|
|
if (!exceptional_return.IsSmi() && exceptional_return.IsNew()) {
|
|
function.SetFfiCallbackExceptionalReturn(Instance::Handle(
|
|
zone, exceptional_return.CopyShallowToOldSpace(thread)));
|
|
} else {
|
|
function.SetFfiCallbackExceptionalReturn(exceptional_return);
|
|
}
|
|
|
|
return function.raw();
|
|
}
|
|
|
|
} // namespace ffi
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace dart
|