[vm] Remove traces of LLVM backend

The code has been dead for quite some time.

TEST=ci

Change-Id: Iddcb63e14e9e4d95230f006ac05da64f444f0712
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/190024
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Vyacheslav Egorov 2021-03-09 20:37:20 +00:00 committed by commit-bot@chromium.org
parent 0e12cdb7fa
commit fa12114202
29 changed files with 0 additions and 3024 deletions

5
.gitignore vendored
View file

@ -23,11 +23,6 @@
/*.vcxproj.user
*.stamp
# LLVM prebuilts
/third_party/llvm/include
/third_party/llvm/lib
/third_party/llvm/.versions
# Gyp generated files
*.xcodeproj
*.intermediate

View file

@ -14,9 +14,6 @@ group("default") {
testonly = true
}
deps = [ ":runtime" ]
if (defined(checkout_llvm) && checkout_llvm) {
deps += [ ":llvm_codegen" ]
}
}
group("most") {
@ -117,21 +114,6 @@ group("analysis_server") {
deps = [ "utils/analysis_server" ]
}
group("check_llvm") {
if (defined(checkout_llvm) && checkout_llvm) {
deps = [ "runtime/llvm_codegen/test" ]
}
}
group("llvm_codegen") {
if (defined(checkout_llvm) && checkout_llvm) {
deps = [
"runtime/llvm_codegen/bit",
"runtime/llvm_codegen/codegen",
]
}
}
# This is the target that is built on the dart2js build bots.
# It must depend on anything that is required by the dart2js
# test suites.

18
DEPS
View file

@ -180,18 +180,10 @@ vars = {
"chrome_tag": "84",
"download_firefox": False,
"firefox_tag": "67",
# An LLVM backend needs LLVM binaries and headers. To avoid build time
# increases we can use prebuilts. We don't want to download this on every
# CQ/CI bot nor do we want the average Dart developer to incur that cost.
# So by default we will not download prebuilts.
"checkout_llvm": False,
"llvm_revision": "fe8bd96ebd6c490ea0b5c1fb342db2d7c393a109"
}
gclient_gn_args_file = Var("dart_root") + '/build/config/gclient_args.gni'
gclient_gn_args = [
'checkout_llvm'
]
deps = {
@ -615,16 +607,6 @@ deps = {
],
"dep_type": "cipd",
},
Var("dart_root") + "/third_party/llvm": {
"packages": [
{
"package": "fuchsia/lib/llvm/${{platform}}",
"version": "git_revision:" + Var("llvm_revision"),
},
],
"condition": "checkout_llvm",
"dep_type": "cipd",
},
Var("dart_root") + "/third_party/browsers/chrome": {
"packages": [
{

View file

@ -897,9 +897,6 @@ executable("run_vm_tests") {
"..:libdart_precompiler",
"//third_party/zlib",
]
if (defined(checkout_llvm) && checkout_llvm) {
deps += [ "//runtime/llvm_codegen/bit:test" ]
}
include_dirs = [
"..",
"$target_gen_dir",

View file

@ -1,32 +0,0 @@
# 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.
executable("bit") {
sources = [ "main.cc" ]
root_dir = rebase_path(root_out_dir)
clang_dir = rebase_path("//buildtools/linux-x64/clang/bin")
defines = [
"BIT_BINARY_DIR=\"$root_dir\"",
"BIT_CLANG_DIR=\"$clang_dir\"",
]
deps = [ "../../../third_party/llvm:LLVMSupport" ]
data_deps = [ "../codegen" ]
}
source_set("test") {
sources = [ "test.cc" ]
root_dir = rebase_path(root_out_dir)
clang_dir = rebase_path("//buildtools/linux-x64/clang/bin")
defines = [
"BIT_BINARY_DIR=\"$root_dir\"",
"BIT_CLANG_DIR=\"$clang_dir\"",
]
deps = [ "../../../third_party/llvm:LLVMSupport" ]
include_dirs = [ "//runtime" ]
defines += [ "TESTING" ]
}

View file

@ -1,80 +0,0 @@
// 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 <stdio.h>
#include <map>
#include <regex>
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/WithColor.h"
namespace {
using namespace llvm;
struct Config {
StringRef filename;
StringRef out_dir;
};
StringMap<std::string> GetSubstitutions(const Config& config) {
// Compute all of our strings needed for substitutions.
StringRef test_dir = sys::path::parent_path(config.filename);
StringRef basename = sys::path::filename(config.filename);
SmallString<128> tmp_file;
sys::path::append(tmp_file, sys::path::Style::native, config.out_dir,
basename + ".tmp");
SmallString<128> codegen;
sys::path::append(codegen, sys::path::Style::native, BIT_BINARY_DIR,
"codegen");
SmallString<128> bit;
sys::path::append(bit, sys::path::Style::native, BIT_BINARY_DIR, "bit");
SmallString<128> clang;
sys::path::append(clang, sys::path::Style::native, BIT_CLANG_DIR, "clang");
// Set up our substitutions.
StringMap<std::string> subs;
subs["s"] = config.filename.str();
subs["p"] = test_dir.str();
subs["P"] = test_dir.str();
subs["t"] = tmp_file.str().str();
subs["{codegen}"] = codegen.str().str();
subs["{bit}"] = bit.str().str();
subs["{clang}"] = clang.str().str();
return subs;
}
std::string PerformSubstitutions(const StringMap<std::string>& subs,
StringRef string) {
std::string out = string.str();
for (const auto& sub : subs) {
std::string key = (Twine("%") + sub.getKeyData()).str();
size_t pos = 0;
while ((pos = out.find(key, pos)) != std::string::npos) {
if (pos != 0 && out[pos - 1] == '%') {
pos += key.size();
continue;
}
out.replace(pos, key.size(), sub.getValue());
pos += sub.second.size();
}
}
return out;
}
Optional<std::string> GetCommand(StringRef line) {
static Regex run_line("^;[ ]*RUN:[ ]*(.*)$");
SmallVector<StringRef, 2> cmd;
if (!run_line.match(line, &cmd)) return Optional<std::string>{};
assert(cmd.size() == 2);
return cmd[1].str();
}
} // namespace

View file

@ -1,122 +0,0 @@
// 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 <stdio.h>
#include <cctype>
#include <map>
#include <regex>
#include "bit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/WithColor.h"
using namespace llvm;
namespace {
StringRef tool_name;
LLVM_ATTRIBUTE_NORETURN void Fail(Twine message) {
WithColor::error(errs(), tool_name) << message << ".\n";
errs().flush();
exit(1);
}
LLVM_ATTRIBUTE_NORETURN void Fail(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);
Fail(createFileError(file, ec));
}
std::string ReadFile(FILE* file) {
std::string output;
constexpr size_t buf_size = 256;
char buf[buf_size];
size_t size;
while ((size = fread(buf, buf_size, sizeof(buf[0]), file)))
output.append(buf, buf + buf_size);
return output;
}
bool IsPosixFullyPortablePath(StringRef path) {
const char* extra = "._-/";
for (auto c : path)
if (!isalnum(c) && !strchr(extra, c)) return false;
return true;
}
} // namespace
int main(int argc, char** argv) {
InitLLVM X(argc, argv);
// Make sure we have both arguments.
tool_name = argv[0];
if (argc != 3) Fail("expected exactly 2 arguments");
// Makes sure that stdin/stdout are setup correctly.
if (sys::Process::FixupStandardFileDescriptors())
Fail("std in/out fixup failed");
// Set our config.
Config config;
config.filename = argv[1];
config.out_dir = argv[2];
// Make sure we have valid filepaths.
if (!IsPosixFullyPortablePath(config.filename))
Fail("'" + config.filename + "' is not a posix fully portable filename");
if (!IsPosixFullyPortablePath(config.out_dir))
Fail("'" + config.out_dir + "' is not a posix fully portable filename");
// Compute substitutions.
auto subs = GetSubstitutions(config);
// The lines we execute are allowed to assume that %p will exist.
sys::fs::create_directory(subs["p"]);
// Open the file for reading.
auto buf_or = vfs::getRealFileSystem()->getBufferForFile(config.filename);
if (!buf_or) ReportError(config.filename, buf_or.getError());
auto buf = std::move(*buf_or);
// Now iterate over the lines in the file.
line_iterator it{*buf};
int count = 0;
for (StringRef line = *it; !it.is_at_end(); line = *++it) {
auto cmd = GetCommand(line);
if (!cmd) continue;
++count;
auto subbed = PerformSubstitutions(subs, *cmd);
FILE* file = popen(subbed.c_str(), "r");
std::string output = ReadFile(file);
if (pclose(file) != 0) {
errs() << output << "\n";
Fail("Failure on line " + Twine(it.line_number()) + "\n\t" + subbed + "");
}
}
if (count == 0) {
Fail("No commands to run");
}
outs() << "Commands run: " << count << "\n";
return 0;
}

View file

@ -1,71 +0,0 @@
// 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 <stdio.h>
#include <utility>
#include <vector>
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/WithColor.h"
#include "platform/assert.h"
#include "vm/unit_test.h"
#define LIT_BINARY_DIR "/path/to/bins"
#include "bit.h"
UNIT_TEST_CASE(BasicGetSubstitutions) {
Config config;
config.filename = "/foo/bar/baz.ll";
config.out_dir = "/test/out/dir";
StringMap<std::string> expected;
expected["s"] = "/foo/bar/baz.ll";
expected["p"] = "/foo/bar";
expected["P"] = "/test/out/dir";
expected["t"] = "/test/out/dir/baz.ll.tmp";
expected["codegen"] = "/path/to/bins/codegen";
expected["bit"] = "/path/to/bins/bit";
StringMap<std::string> actual = GetSubstitutions(config);
EXPECT_EQ(actual.size(), expected.size());
for (const auto& p : actual)
EXPECT_EQ(p.getValue(), expected[p.getKey()]);
}
UNIT_TEST_CASE(BasicPerformSubstitutions) {
StringMap<std::string> subs;
subs["foo"] = "/foo/path";
subs["bar"] = "/bar/path";
subs["baz"] = "/baz/path";
std::vector<std::pair<std::string, std::string>> cases = {
{"%foo", "/foo/path"},
{"%bar", "/bar/path"},
{"%baz", "/baz/path"},
{"this has %foo, and %bar, and %baz2",
"this has /foo/path, and /bar/path, and /baz/path2"},
{"we don't want %this to expand", "we don't want %this to expand"},
{"%", "%"}};
for (const auto& test : cases) {
auto out = PerformSubstitutions(subs, test.first);
EXPECT_EQ(out, test.second);
}
}
UNIT_TEST_CASE(BasicGetCommand) {
EXPECT(!GetCommand("; this is some test"));
EXPECT(!GetCommand("2 + 2"));
EXPECT(!GetCommand("echo $VAR > %bit"));
EXPECT(GetCommand(";RUN: blarg") == Optional<std::string>{"blarg"});
EXPECT(GetCommand("; RUN: foo") == Optional<std::string>{"blarg"});
EXPECT(
GetCommand("; RUN: echo %bit %p/Input/$(%t2) > $(baz \"$BAR->%t\")") ==
Optional<std::string>("echo %bit %p/Input/$(%t2) > $(baz \"$BAR->%t\")"));
}

View file

@ -1,41 +0,0 @@
# 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.
import("../../vm/compiler/compiler_sources.gni")
config("config") {
include_dirs = [ "../../" ]
cflags = [ "-Wno-unused-private-field" ]
}
_lib_llvm_so = "../../../third_party/llvm/lib/libLLVM-9svn.so"
config("llvm") {
include_dirs = [ "../../../third_party/llvm/include" ]
libs = [ _lib_llvm_so ]
}
copy("lib_llvm") {
sources = [ _lib_llvm_so ]
outputs = [ "$root_out_dir/libLLVM-9svn.so" ]
public_configs = [ ":llvm" ]
}
executable("codegen") {
sources = [
"custom_zone.cc",
"custom_zone.h",
"dart.cc",
"dart.h",
"main.cc",
]
deps = [
":lib_llvm",
"../../third_party/double-conversion/src:libdouble_conversion",
]
configs += [ ":config" ]
}

View file

@ -1,54 +0,0 @@
// 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

View file

@ -1,52 +0,0 @@
// 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_

View file

@ -1,358 +0,0 @@
// 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 <utility>
#include "dart.h"
#include "llvm/ADT/StringSwitch.h"
using namespace llvm;
Value* DartThreadObject::GetOffset(Type* type, intptr_t offset) const {
auto& ctx = bb_builder_.Context();
auto& builder = bb_builder_.Builder();
auto int64ty = IntegerType::getInt64Ty(ctx);
// TODO: This is only correct for x86_64. On x86 we need to use 257,
// and only arm targets an entirely different mechanism will be
// required since there isn't an unused register. On Arm we can
// probably still use the thread register as long as we're careful
// to set it back on thread boundaries.
// On x86_64 fs (257) is used for TLS but gs (256) is unused
// On x86 gs (256) is used for TLS but fs (257) is unused
// we use the unused segment so as to not conflict with TLS which
// allows linking against native code that uses TLS without needing
// to handle any kind of context switching.
constexpr unsigned kDartThreadPointerAddressSpace = 256;
auto* ptr_tls = PointerType::get(type, kDartThreadPointerAddressSpace);
auto* offset_value = ConstantInt::get(int64ty, offset);
auto* tls_value = builder.CreateIntToPtr(offset_value, ptr_tls);
return builder.CreateLoad(tls_value);
}
Value* DartThreadObject::StackLimit() const {
auto& ctx = bb_builder_.Context();
return GetOffset(IntegerType::getInt64Ty(ctx), kThreadStackLimitOffset);
}
Value* BasicBlockBuilder::GetValue(const DartValue* v) {
auto iter = values_.find(v);
if (iter == values_.end()) {
auto* out = v->Make(*this);
values_[v] = out;
return out;
}
return iter->second;
}
DartInstruction::~DartInstruction() {}
static Error CreateError(const Twine& err) {
return make_error<StringError>(err, inconvertibleErrorCode());
}
Value* DartConstant::Make(BasicBlockBuilder& bb_builder) const {
auto& ctx = bb_builder.Context();
switch (type) {
case DartConstant::Type::String:
auto constant = ConstantDataArray::getString(ctx, str);
auto gv =
new GlobalVariable(bb_builder.Module(), constant->getType(), true,
GlobalVariable::ExternalLinkage, constant);
return ConstantExpr::getBitCast(gv, GetType(bb_builder));
}
}
Type* DartConstant::GetType(BasicBlockBuilder& bb_builder) const {
// TODO: Right now this returns a c-string type but that's not correct.
// We should move this to a generic object type (e.g. a tagged pointer).
auto& ctx = bb_builder.Context();
auto int8ty = IntegerType::getInt8Ty(ctx);
return PointerType::get(int8ty, 0);
}
void InstCheckStackOverflow::Build(BasicBlockBuilder& bb_builder) const {
auto& builder = bb_builder.Builder();
auto& ctx = bb_builder.Context();
auto& module = bb_builder.Module();
auto& thread_object = bb_builder.ThreadObject();
// TODO: This is only correct on 64-bit architectures.
auto int64ty = IntegerType::getInt64Ty(ctx);
// Get the stack pointer.
auto spi_type = Intrinsic::getType(ctx, Intrinsic::stacksave);
auto spi_func = Intrinsic::getDeclaration(&module, Intrinsic::stacksave);
auto sp_raw = builder.CreateCall(spi_type, spi_func);
auto sp = builder.CreatePtrToInt(sp_raw, int64ty);
// Get the stack limit from the thread pointer.
auto stack_limit = thread_object.StackLimit();
// Now compare the stack pointer and limit.
auto error_bb = bb_builder.AddBasicBlock();
auto cont_bb = bb_builder.AddBasicBlock();
auto cmp = builder.CreateICmpULT(sp, stack_limit);
builder.CreateCondBr(cmp, error_bb, cont_bb);
// Now build the error path.
// TODO: Don't just trap here. For now we just trap rather than
// handling the proper exceptional control flow here.
builder.SetInsertPoint(error_bb);
auto trap_type = Intrinsic::getType(ctx, Intrinsic::trap);
auto trap_func = Intrinsic::getDeclaration(&module, Intrinsic::trap);
builder.CreateCall(trap_type, trap_func);
builder.CreateBr(cont_bb);
// Now pretend as if this new block is just the end of the block we
// started with.
builder.SetInsertPoint(cont_bb);
}
Expected<std::unique_ptr<DartInstruction>> InstCheckStackOverflow::Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder) {
// inst = (CheckStackoverflow)
return llvm::make_unique<InstCheckStackOverflow>();
}
void InstPushArgument::Build(BasicBlockBuilder& bb_builder) const {
bb_builder.PushArgument(bb_builder.GetValue(arg_));
}
Expected<std::unique_ptr<DartInstruction>> InstPushArgument::Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder) {
// inst = (PushArgument <arg>)
if (inst->Length() != 2) {
return CreateError("PushArgument should have exactly 1 argument");
}
dart::SExpSymbol* arg = inst->At(1)->AsSymbol();
if (arg == nullptr) {
return CreateError("Expected PushArgument's argument to be a symbol");
}
const DartValue* dvalue = bb_builder.GetDef(arg->value());
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> ...)
SmallVector<Value*, 8> args;
size_t arg_count = args_len_;
while (arg_count > 0) {
arg_count--;
args.push_back(bb_builder.PopArgument());
}
auto& builder = bb_builder.Builder();
// Hard code the function type for now.
auto& ctx = bb_builder.Context();
auto int8ty = IntegerType::getInt8Ty(ctx);
auto i8ptr = PointerType::get(int8ty, 0);
SmallVector<Type*, 8> arg_types;
arg_types.push_back(i8ptr);
auto print_type = FunctionType::get(Type::getVoidTy(ctx), arg_types, false);
// Get the function value we need.
auto func = bb_builder.GetValue(function_);
builder.CreateCall(print_type, func, args);
}
Expected<std::unique_ptr<DartInstruction>> InstStaticCall::Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder) {
// inst = (StaticCall <function_name> { args_len <N> })
if (inst->Length() != 2) {
return CreateError("StaticCall should have exactly 1 argument");
}
dart::SExpSymbol* func = inst->At(1)->AsSymbol();
if (!func) {
return CreateError("Expected StaticCall's argument to be a symbol");
}
const DartValue* dvalue = bb_builder.GetDef(func->value());
dart::SExpression* args_len_expr = inst->ExtraLookupValue("args_len");
// If args_len_expr isn't found args_len is assumed to be zero.
size_t args_len = 0;
if (args_len_expr) {
dart::SExpInteger* args_len_expr_int = args_len_expr->AsInteger();
if (args_len_expr_int) args_len = args_len_expr_int->value();
}
return llvm::make_unique<InstStaticCall>(dvalue, 1);
}
void InstReturn::Build(BasicBlockBuilder& bb_builder) const {
auto& builder = bb_builder.Builder();
builder.CreateRetVoid();
}
Expected<std::unique_ptr<DartInstruction>> InstReturn::Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder) {
// inst = (Return)
return llvm::make_unique<InstReturn>();
}
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));
}
if (def->Length() != 3) {
return CreateError("Constant definitions must have exactly 3 lines");
}
dart::SExpSymbol* def_symbol = def->At(0)->AsSymbol();
if (def_symbol->value() != StringRef("def")) {
return CreateError(
"first element in a constant definition expected to be `def`");
}
dart::SExpSymbol* def_name = def->At(1)->AsSymbol();
if (!def_name) {
return CreateError("element after `def` in constant expected to be name");
}
dart::SExpression* def_value = def->At(2);
if (def_value->IsString()) {
constant.str = def_value->AsString()->value();
constant.type = DartConstant::Type::String;
} else {
return CreateError("We can't yet handle that element type");
}
out[def_name->value()] = constant;
}
return out;
}
#define FOREACH_INSTRUCTION(M) \
M(CheckStackOverflow) \
M(PushArgument) \
M(StaticCall) \
M(Return)
static Expected<std::unique_ptr<DartInstruction>> MakeInstruction(
dart::SExpList* sexpr,
DartBasicBlockBuilder& bb_builder) {
if (sexpr->Length() < 1)
return CreateError("An empty list can't be an instruction");
dart::SExpSymbol* inst_sym = sexpr->At(0)->AsSymbol();
if (!inst_sym)
return CreateError(
"Expected first element of list in instruction to be a symbol");
using CtorFunc = std::function<Expected<std::unique_ptr<DartInstruction>>(
dart::SExpList*, DartBasicBlockBuilder&)>;
CtorFunc ctor = StringSwitch<CtorFunc>(inst_sym->value())
#define HANDLE_INSTRUCTION_CASE(INST) .Case(#INST, Inst##INST::Construct)
FOREACH_INSTRUCTION(HANDLE_INSTRUCTION_CASE);
#undef HANDLE_INSTRUCTION_CASE
return ctor(sexpr, bb_builder);
}
static Expected<DartBlock> MakeBlock(dart::SExpList* sexpr,
DartFunction& function,
const StringMap<const DartValue*>& env) {
// Construct the basic block builder
DartBasicBlockBuilder bb_builder;
for (const auto& c : function.constants)
bb_builder.AddDef(c.getKey(), &c.getValue());
for (const auto& c : env)
bb_builder.AddDef(c.getKey(), c.getValue());
DartBlock out;
// Make sure we have a basic block and get the name
if (sexpr->Length() <= 2)
return CreateError("too few elements in basic block");
dart::SExpSymbol* block_name = sexpr->At(1)->AsSymbol();
if (!block_name)
return CreateError("expected block name after `block` symbol");
out.name = block_name->value();
// Now construct each instruction and add it to the basic block
for (intptr_t i = 2; i < sexpr->Length(); ++i) {
dart::SExpList* inst = sexpr->At(i)->AsList();
if (!inst)
return CreateError("stray token at element " + Twine(i) +
" in basic block " + out.name);
auto inst_or = MakeInstruction(inst, bb_builder);
if (!inst_or) return inst_or.takeError();
out.instructions.emplace_back(std::move(*inst_or));
}
return out;
}
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::SExpList* flist = sexpr->AsList();
if (!flist) return CreateError("S-Expression was not a function list");
if (flist->Length() < 2)
return CreateError("S-Expression list was too short to be a function");
dart::SExpSymbol* function_symbol = flist->At(0)->AsSymbol();
if (function_symbol == nullptr ||
function_symbol->value() != StringRef("function"))
return CreateError(
"S-Expression cannot be a function as it does not start with "
"`function`");
dart::SExpSymbol* function_name = flist->At(1)->AsSymbol();
if (function_name == nullptr)
return CreateError("Expected symbol name after `function` symbol");
// Now we fill in all the details
DartFunction function;
function.name = function_name->value();
Optional<StringRef> normal_entry;
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) {
return CreateError(Twine("Stray token in function at location ") +
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) +
" of function to start with a symbol");
StringRef chunk_tag = chunk_symbol->value();
if (chunk_tag == "constants") {
auto constants = MakeConstants(zone, chunk);
if (!constants) return constants.takeError();
function.constants = std::move(*constants);
}
if (chunk_tag == "block") {
auto block = MakeBlock(chunk, function, env);
if (!block) return block.takeError();
StringRef name = block->name;
function.blocks[name] = std::move(*block);
}
if (chunk_tag == "normal-entry") {
if (chunk->Length() != 2)
return CreateError("Expected 1 argument to normal-entry");
dart::SExpSymbol* block_name = chunk->At(1)->AsSymbol();
if (!block_name)
return CreateError("expected block name after normal-entry symbol");
normal_entry = block_name->value();
}
}
if (normal_entry) {
auto iter = function.blocks.find(*normal_entry);
if (iter != function.blocks.end())
function.normal_entry = &iter->getValue();
} else {
function.normal_entry = nullptr;
}
return function;
}

View file

@ -1,314 +0,0 @@
// 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_DART_H_
#define RUNTIME_LLVM_CODEGEN_CODEGEN_DART_H_
#include <memory>
#include <vector>
#include <string>
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#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
// S-Expressions and llvm IR. To explain how each part is intended
// to be roughly translated using these I'll provide a mapping
// showing how each part is translated.
// At a high level two translations are very seamless:
//
// (function foo ...) -> DartFunction -> llvm::Function*
// (block B ...) -> DartBlock -> (sort of) llvm::BasicBlock*
//
// Internally within a function constants are given names and are then used in
// blocks. Each block additionally defines more names. Each of these names
// needs to be mapped to a DartValue (more on that later) so a context to help
// keep track of these name to DartValue mappings called a
// DartBasicBlockBuilder exists. It is only used for to aid in the
// (block B ...) -> DartBlock translation which is in turn used in the
// (function foo ...) -> DartFunction translation. DartFunctions and DartBlocks
// can be seen as validated representations of their S-Expression forms.
// Within a DartBlock we have DartInstructions. Each DartInstruction either
// has some effect (like calling a function or updating a value) or defines
// a new name mapping it to a DartValue later. DartValues are referenced as
// arguments to DartInstructions and map to llvm::Value*s. DartInstructions
// have no analogue which they're directly translated to in code but they
// do closely correspond mentally to llvm::Instruction*. The challenge is that
// a DartInstruction might map to a near arbitrary number of llvm Instructions
// and that mapping is very dependent on context. So instead of mapping them
// to objects DartInstructions just know how to add their llvm Instructions to
// an llvm::BasicBlock. These instructions might reference a verity of context
// and so BasicBlockBuilder is passed in to provide them with this context.
// Each DartInstruction is expected to already hold each DartValue that it
// needs as previously supplied by the DartBasicBlockBuilder on construction.
// An additional issue arises when translating DartInstructions into llvm IR.
// Many require introducing control flow when lowered to the level of llvm IR
// but this requires using multiple llvm::BasicBlock for a single DartBlock.
// Luckily each DartInstruction that is not a terminator is expected to make it
// possible for all non-exceptional control flow paths to wind up at a single
// basic block. Since BasicBlockBuilder keeps track of a "current" basic block
// via llvm::IRBuilder we simply ensure that after generating many blocks we
// end each instruction which requires new basic blocks on this final basic
// block that all generated blocks flow into. A picture better explains this:
// Say you have a DartBlock B_1 it would then be mapped to llvm blocks that
// look like this:
//
// B_1
// / \
// / \
// B_1_left B_1_right
// \ /
// \ /
// B_1_0
//
// And then we go on adding to B_1_0 as if it were the end of B_1 from before.
// Each DartValue knows how to map itself to an llvm::Value. In llvm a Value
// is really just anything you can give a name to in the IR but a DartValue
// is intended to be more specific, it's a compile time representation of a
// object, be it an integer, a tagged SMI, a pointer to a Dart Object, etc...
// its intended to correspond to some actual object that we're computing on.
// Class FunctionBuilder provides functionality for building
// and LLVM function object including the ability to add a
// named basic block, find an existing block, get the current
// context/module and additionally retrieve llvm Values valid
// in the current function.
class FunctionBuilder {
public:
FunctionBuilder(llvm::LLVMContext& ctx,
llvm::Module& mod,
llvm::Function& func)
: ctx_(ctx), mod_(mod), func_(func) {}
llvm::LLVMContext& Context() { return ctx_; }
llvm::Module& Module() { return mod_; }
llvm::Value* GetSymbolValue(llvm::StringRef name) {
auto* symtab = func_.getValueSymbolTable();
return symtab->lookup(name);
}
llvm::BasicBlock* AddBasicBlock() {
return llvm::BasicBlock::Create(ctx_, "", &func_);
}
llvm::BasicBlock* AddBasicBlock(llvm::StringRef name) {
auto* bb = llvm::BasicBlock::Create(ctx_, name, &func_);
basic_blocks_[name] = bb;
return bb;
}
llvm::BasicBlock* GetBasicBlock(llvm::StringRef name) const {
auto iter = basic_blocks_.find(name);
if (iter != basic_blocks_.end()) return iter->getValue();
return nullptr;
}
private:
llvm::LLVMContext& ctx_;
llvm::Module& mod_;
llvm::Function& func_;
llvm::StringMap<llvm::BasicBlock*> basic_blocks_;
};
class BasicBlockBuilder;
// TODO(jakehehrlich): Make this architecture dependent
// Class DartThreadObject is used as a high level object for generating
// code that reads fields from the thread object.
class DartThreadObject {
public:
explicit DartThreadObject(BasicBlockBuilder& bb_builder)
: bb_builder_(bb_builder) {}
// StackLimit returns an llvm::Value representing the stack limit
// of the thread object.
llvm::Value* StackLimit() const;
private:
static constexpr intptr_t kThreadStackLimitOffset = 72;
BasicBlockBuilder& bb_builder_;
// GetOffset returns an llvm::Value* representing a pointer to a particular
// field of the thread object. It adds the specified offset to the thread
// pointer, and then casts to the specified type.
llvm::Value* GetOffset(llvm::Type* type, intptr_t offset) const;
};
class DartValue;
// A class for keeping track of the basic block state and SSA values.
// This is similar to IRBuilder but also keeps track of the argument stack and
// basic block names.
class BasicBlockBuilder {
public:
BasicBlockBuilder(llvm::BasicBlock* bb, FunctionBuilder& fb)
: fb_(fb), top_(bb), builder_(bb), thread_object_(*this) {}
llvm::LLVMContext& Context() { return fb_.Context(); }
llvm::Module& Module() { return fb_.Module(); }
llvm::IRBuilder<>& Builder() { return builder_; }
const DartThreadObject& ThreadObject() { return thread_object_; }
llvm::BasicBlock* AddBasicBlock() { return fb_.AddBasicBlock(); }
llvm::BasicBlock* GetBasicBlock(llvm::StringRef Name) const {
return fb_.GetBasicBlock(Name);
}
llvm::Value* GetSymbolValue(llvm::StringRef name) const {
return fb_.GetBasicBlock(name);
}
llvm::Value* GetValue(const DartValue* v);
void PushArgument(llvm::Value* v) { stack_.push_back(v); }
llvm::Value* PopArgument() {
llvm::Value* out = stack_.back();
stack_.pop_back();
return out;
}
private:
FunctionBuilder& fb_;
llvm::BasicBlock* top_;
llvm::SmallVector<llvm::Value*, 16> stack_;
llvm::IRBuilder<> builder_;
llvm::DenseMap<const DartValue*, llvm::Value*> values_;
DartThreadObject thread_object_;
};
// Class DartValue represents an SSA value from the Dart SSA
// such that it can be converted into an llvm::Value*.
class DartValue {
public:
virtual ~DartValue() {}
virtual llvm::Value* Make(BasicBlockBuilder& bb_builder) const = 0;
virtual llvm::Type* GetType(BasicBlockBuilder& bb_builder) const = 0;
};
// Class DartBasicBlockBuilder provides helpful context for going
// from an S-Expression basic block to a DartBlock. It just lets
// one lookup DartValue's by name at this time.
class DartBasicBlockBuilder {
public:
void AddDef(llvm::StringRef name, const DartValue* v) { defs_[name] = v; }
const DartValue* GetDef(llvm::StringRef name) const {
auto iter = defs_.find(name);
if (iter != defs_.end()) return iter->getValue();
return nullptr;
}
private:
llvm::StringMap<const DartValue*> defs_;
};
// A DartConstant is a DartValue for a constant.
class DartConstant : public DartValue {
public:
std::string str;
enum class Type { String };
Type type;
llvm::Value* Make(BasicBlockBuilder& bb_builder) const override;
llvm::Type* GetType(BasicBlockBuilder& bb_builder) const override;
};
// Class DartInstruction represents a step within a DartBasicBlock.
// CheckStackOverflow or PushArgument are instructions. They contain
// DartValues as arguments typically. SSA definitions are also
// DartInstructions which assign DartValues to names in the function's
// context.
class DartInstruction {
public:
virtual ~DartInstruction();
virtual void Build(BasicBlockBuilder& bb_builder) const = 0;
};
// Class InstCheckStackOverflow is a DartInstruction that represents
// an instance of a CheckStackOverflow instruction.
class InstCheckStackOverflow : public DartInstruction {
public:
InstCheckStackOverflow() {}
~InstCheckStackOverflow() override {}
void Build(BasicBlockBuilder& bb_builder) const override;
static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder);
};
// Class InstPushArgument is a DartInstruction that represents
// and instance of a PushArgument Instruction.
class InstPushArgument : public DartInstruction {
public:
explicit InstPushArgument(const DartValue* arg) : arg_(arg) {}
~InstPushArgument() override {}
void Build(BasicBlockBuilder& bb_builder) const override;
static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder);
private:
const DartValue* arg_;
};
// Class InstStaticCall is a DartInstruction that represents a
// StaticCall instruction.
class InstStaticCall : public DartInstruction {
public:
InstStaticCall(const DartValue* func, size_t args_len)
: function_(func), args_len_(args_len) {}
~InstStaticCall() override {}
void Build(BasicBlockBuilder& bb_builder) const override;
static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder);
private:
const DartValue* function_;
size_t args_len_;
};
// Class InstReturn is a DartInstruction that represents a Return
// instruction.
class InstReturn : public DartInstruction {
public:
InstReturn() {}
~InstReturn() override {}
void Build(BasicBlockBuilder& bb_builder) const override;
static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
dart::SExpList* inst,
DartBasicBlockBuilder& bb_builder);
};
// Class DartBlock represents a validated basic block as parsed from
// a (block ...) S-Expression.
struct DartBlock {
std::string name;
std::vector<std::unique_ptr<DartInstruction>> instructions;
};
// Class DartFunction represents a validated function parsed from a
// (function ...) S-Expression.
struct DartFunction {
std::string name;
DartBlock* normal_entry;
llvm::StringMap<DartConstant> constants;
llvm::StringMap<DartBlock> blocks;
};
// MakeFunction takes an S-Expression and an environment of externally
// defined DartValues and produces a DartFunction corresponding to the
// S-Expression if everything is valid. If something about the syntax
// 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_

View file

@ -1,150 +0,0 @@
// 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;
}

View file

@ -1,10 +0,0 @@
# 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.
group("test") {
deps = [
"bit",
"codegen",
]
}

View file

@ -1,9 +0,0 @@
# 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.
import("../bit_test.gni")
bit_test("bit") {
tests = [ "basic.test" ]
}

View file

@ -1 +0,0 @@
; RUN: %{codegen} %p/../../codegen/Inputs/hello.sexp

View file

@ -1 +0,0 @@
this is a percent sign: %

View file

@ -1,8 +0,0 @@
; RUN: echo this is a test > %t1
; RUN: echo this is a test > %t2
; RUN: cmp %t1 %t2
; RUN: echo this is a percent sign: % > %t3
; RUN: cmp %t3 %p/Inputs/percent.test
; RUN: %{bit} %p/Inputs/basic_input.test %P > %t.test
; RUN: echo Commands run: 1 > %t.test2
; RUN: cmp %t.test %t.test2

View file

@ -1,38 +0,0 @@
# 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.
import("../../../build/executable_suffix.gni")
# This file defines a template for running bit tests.
#
# - bit_test()
# Runs bit on the specified file.
# A template for running bit. This lets bit commands be run as ninja commands.
#
# Parameters:
# tests:
# The list of files to input into bit
template("bit_test") {
assert(defined(invoker.tests), "tests must be defined for $target_name")
action_foreach(target_name) {
script = "//runtime/llvm_codegen/test/run_bit.py"
sources = invoker.tests
deps = [ "../../bit" ]
inputs = [ "${root_out_dir}/bit$executable_suffix" ]
# This output is always dirty so ninja will always run this step when asked to.
outputs = [ "$target_gen_dir/{{source_name_part}}}" ]
args = [
"--bit",
rebase_path("${root_out_dir}/bit"),
"--test",
"{{source}}",
"--out",
rebase_path(target_gen_dir),
]
}
}

View file

@ -1,9 +0,0 @@
# 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.
import("../bit_test.gni")
bit_test("codegen") {
tests = [ "hello.test" ]
}

View file

@ -1 +0,0 @@
Hello, World!

View file

@ -1,35 +0,0 @@
; ModuleID = '../../runtime/llvm_codegen/test/codegen/Inputs/hello.sexp'
source_filename = "../../runtime/llvm_codegen/test/codegen/Inputs/hello.sexp"
@0 = constant [14 x i8] c"Hello, World!\00"
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
4: ; preds = %B1
call void @llvm.trap()
br label %5
5: ; preds = %4, %B1
call void @"dart:core::print"(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @0, i32 0, i32 0))
ret void
}
; Function Attrs: nounwind
declare i8* @llvm.stacksave() #0
; Function Attrs: cold noreturn nounwind
declare void @llvm.trap() #1
declare void @"dart:core::print"(i8*)
; Function Attrs: nounwind
declare void @llvm.stackprotector(i8*, i8**) #0
attributes #0 = { nounwind }
attributes #1 = { cold noreturn nounwind }

View file

@ -1,9 +0,0 @@
(function hello.dart::main
(constants
(def v2 "Hello, World!"))
(normal-entry B1)
(block B1
(CheckStackOverflow)
(PushArgument v2)
(StaticCall dart:core::print { args_len 1, env (v0 arg[0]), })
(Return v0)))

View file

@ -1,38 +0,0 @@
// 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.
.data
.type _threadObject,@object
.size _threadObject,1400
_threadObject:
.fill 1400
.text
.file "runtime.S"
.globl main
.type main,@function
.globl "dart:core::print"
.type "dart:core::print",@function
.globl arch_prctl
.type arch_prctl,@function
main:
movq %rsp, %rax
subq $0x1000, %rax
movq %rax, [_threadObject + 72]
# Pass ARCH_SET_GS
movq $0x1001, %rdi
# Pass $_threadObject
movq $_threadObject, %rsi
callq arch_prctl
callq "hello.dart::main"
ret
"dart:core::print":
callq puts
ret

View file

@ -1,6 +0,0 @@
; RUN: %{codegen} %p/Inputs/hello.sexp --dump-obj %t.o > %t.ll
; RUN: diff %t.ll %p/Inputs/hello.ll.expected
; RUN: %{clang} -g -c %p/Inputs/runtime.S -o %t.runtime.o
; RUN: %{clang} %t.o %t.runtime.o -o %t.hello.exe
; RUN: %t.hello.exe > %t.hello.exe.stdout
; RUN: diff %t.hello.exe.stdout %p/Inputs/hello.expected

View file

@ -1,15 +0,0 @@
# 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.
import subprocess
import argparse
parser = argparse.ArgumentParser(description="A tool to run the bit integration tester")
parser.add_argument("--bit", help="Sets the path to bit")
parser.add_argument("--test", help="Path to test to be run")
parser.add_argument("--out", help="Path to out directory")
args = parser.parse_args()
subprocess.check_call([args.bit, args.test, args.out])

View file

@ -108,12 +108,6 @@ final Set<String> excludedFiles = Set<String>.from([
'runtime/vm/stack_frame_ia32.h',
'runtime/vm/stack_frame_x64.h',
// By default the gclient checkout doesn't have llvm pulled in.
'runtime/llvm_codegen/bit/bit.h',
'runtime/llvm_codegen/bit/main.cc',
'runtime/llvm_codegen/bit/test.cc',
'runtime/llvm_codegen/codegen/main.cc',
// Only available in special builds
'runtime/bin/io_service_no_ssl.h',
'runtime/bin/utils_win.h',

File diff suppressed because it is too large Load diff