Skip to content

Commit

Permalink
Complete Basic Test Automation
Browse files Browse the repository at this point in the history
  • Loading branch information
XChy committed Aug 4, 2023
1 parent 90b2c4e commit cd5c956
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 56 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,4 @@ testcases/string
testcases/string
testcases/string.xsharp.bc
testcases/string.xsharp.o
LLVMIR/test/temp
12 changes: 8 additions & 4 deletions LLVMIR/ControlFlow/ControlFlowProxies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ ValueAndType CodeGenProxy<ContinueNode>::codeGen(ContinueNode* ast,
const Generator& generator)
{
using llvm::BasicBlock;
assertWithError(!ctx->loops.empty(), ctx->error, "No loop to continue", 0);
assertWithError(!ctx->loops.empty(), ctx->error,
"Expected loop to continue", 0);

if (!ctx->llvm_builder.GetInsertBlock()->getTerminator()) {
ctx->llvm_builder.CreateBr(ctx->loops.top().cond);
Expand All @@ -133,10 +134,11 @@ ValueAndType CodeGenProxy<BreakNode>::codeGen(BreakNode* ast,
const Generator& generator)
{
using llvm::BasicBlock;
assertWithError(!ctx->loops.empty(), ctx->error, "No loop to break", 0);
assertWithError(!ctx->loops.empty(), ctx->error, "Expected loop to break",
0);

if (!ctx->llvm_builder.GetInsertBlock()->getTerminator()) {
auto i = ctx->llvm_builder.CreateBr(ctx->loops.top().end);
ctx->llvm_builder.CreateBr(ctx->loops.top().end);
BasicBlock* deadblock =
BasicBlock::Create(ctx->llvm_ctx, "deadblock",
ctx->llvm_builder.GetInsertBlock()->getParent());
Expand Down Expand Up @@ -164,7 +166,9 @@ ValueAndType CodeGenProxy<ReturnNode>::codeGen(ReturnNode* ast,
ret_type->typeName(), ctx->retTypes.top()->typeName());

return {builder.CreateRet(ret_val), XSharp::getVoidType()};
} else {
} else if (ctx->retTypes.top()->equals(Types::get("void"))) {
return {builder.CreateRetVoid(), getVoidType()};
}

return {nullptr, nullptr};
}
16 changes: 7 additions & 9 deletions LLVMIR/LLVMTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ llvm::Type* castToLLVM(XSharp::Type* type, llvm::LLVMContext& context)
{
std::byte a;
using XSharp::BasicType;
// TODO complete XSharp's Type to Variable
using XSharp::Type;
using llvm::SmallVector;

switch (type->category) {
case Type::Basic:
Expand Down Expand Up @@ -47,7 +47,7 @@ llvm::Type* castToLLVM(XSharp::Type* type, llvm::LLVMContext& context)
}

case Type::Function: {
std::vector<llvm::Type*> llvmTypesForParams;
SmallVector<llvm::Type*> llvmTypesForParams;
for (XSharp::Type* paramType : type->parameterTypes())
llvmTypesForParams.push_back(castToLLVM(paramType, context));

Expand All @@ -56,12 +56,6 @@ llvm::Type* castToLLVM(XSharp::Type* type, llvm::LLVMContext& context)
llvmTypesForParams, false);
}

case Type::Array: {
// Allocate XSharp's array on heap
// So the type of array is the pointer type of its element
return llvm::PointerType::get(context, 0);
}

case Type::Class: {
std::vector<llvm::Type*> llvmTypes;

Expand All @@ -76,8 +70,8 @@ llvm::Type* castToLLVM(XSharp::Type* type, llvm::LLVMContext& context)
return structType;
}

case Type::Array:
case Type::Closure:
break;
case Type::Reference:
return llvm::PointerType::get(context, 0);
default:
Expand All @@ -89,9 +83,13 @@ llvm::Type* castToLLVM(XSharp::Type* type, llvm::LLVMContext& context)

llvm::StructType* structForArray(llvm::LLVMContext& context)
{
// Allocate XSharp's array on heap
// So the type of array is the pointer type of its element

return llvm::StructType::get(context,
{castToLLVM(getArrayLenType(), context),
llvm::PointerType::get(context, 0)});
}

} // namespace LLVMCodeGen
} // namespace XSharp
11 changes: 6 additions & 5 deletions LLVMIR/Optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,20 @@ Optimizer::Optimizer(llvm::Module* module) : functionPassManager(module)
// promote memory allocation to register allocation
functionPassManager.add(llvm::createPromoteMemoryToRegisterPass());
// simplify looping
functionPassManager.add(llvm::createLoopSimplifyPass());
functionPassManager.add(llvm::createEarlyCSEPass(true));
functionPassManager.add(llvm::createCFGSimplificationPass());
functionPassManager.add(llvm::createStructurizeCFGPass());
functionPassManager.add(llvm::createInstSimplifyLegacyPass());
functionPassManager.add(llvm::createIndVarSimplifyPass());
functionPassManager.add(llvm::createFloat2IntPass());
functionPassManager.add(llvm::createConstraintEliminationPass());
functionPassManager.add(llvm::createCFGSimplificationPass());
functionPassManager.add(llvm::createGVNPass());
functionPassManager.add(llvm::createNewGVNPass());
functionPassManager.add(llvm::createReassociatePass());
functionPassManager.add(llvm::createMemCpyOptPass());
functionPassManager.add(llvm::createLoopStrengthReducePass());
functionPassManager.add(llvm::createFloat2IntPass());
functionPassManager.add(llvm::createLICMPass());
functionPassManager.add(llvm::createInstructionCombiningPass());
functionPassManager.add(llvm::createReassociatePass());
functionPassManager.add(llvm::createConstraintEliminationPass());
functionPassManager.add(llvm::createLoopSinkPass());
functionPassManager.add(llvm::createGVNSinkPass());
Expand All @@ -45,14 +44,16 @@ Optimizer::Optimizer(llvm::Module* module) : functionPassManager(module)
functionPassManager.add(llvm::createDeadStoreEliminationPass());
functionPassManager.add(llvm::createLibCallsShrinkWrapPass());
functionPassManager.add(llvm::createSeparateConstOffsetFromGEPPass());
functionPassManager.add(llvm::createLoopSimplifyPass());
functionPassManager.add(llvm::createMergedLoadStoreMotionPass());
functionPassManager.add(llvm::createTailCallEliminationPass());
functionPassManager.add(llvm::createVectorCombinePass());
functionPassManager.add(llvm::createLoadStoreVectorizerPass());
functionPassManager.add(llvm::createInferAddressSpacesPass());
functionPassManager.add(llvm::createSeparateConstOffsetFromGEPPass());
functionPassManager.add(llvm::createGVNPass());
functionPassManager.add(llvm::createNewGVNPass());
functionPassManager.add(llvm::createScalarizeMaskedMemIntrinLegacyPass());
functionPassManager.add(llvm::createEarlyCSEPass(true));
functionPassManager.doInitialization();

modulePassManager.add(llvm::createFunctionInliningPass());
Expand Down
10 changes: 5 additions & 5 deletions LLVMIR/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,17 @@ llvm::Value* genArrayMalloc(CodeGenContext* helper, XSharp::Type* type,
llvm::Value* array_value =
helper->llvm_builder.CreateAlloca(array_struct_type);

auto elements_ptr =
auto elementsPtr =
helper->llvm_builder.CreateCall(newFunc, {sizeofArray});

auto length_ptr = helper->llvm_builder.CreateStructGEP(
auto lengthPtr = helper->llvm_builder.CreateStructGEP(
array_struct_type, array_value, 0);

auto elements_ptr_ptr = helper->llvm_builder.CreateStructGEP(
auto elementsPtrPtr = helper->llvm_builder.CreateStructGEP(
array_struct_type, array_value, 1);

helper->llvm_builder.CreateStore(element_count, length_ptr);
helper->llvm_builder.CreateStore(elements_ptr, elements_ptr_ptr);
helper->llvm_builder.CreateStore(element_count, lengthPtr);
helper->llvm_builder.CreateStore(elementsPtr, elementsPtrPtr);

return array_value;

Expand Down
16 changes: 7 additions & 9 deletions XSharpCLI/xsharpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <string.h>
#include <unistd.h>

#include "XSharp/XSharpEngine.h"
#include "XSharp/XString.h"

int compile(const char *path);
Expand All @@ -32,7 +31,8 @@ int main(int argc, char *argv[])
CLI::App app("The compiler of XSharp");
app.add_flag("-L,--emit-llvm-ir", emitLLVMIR, "Emit LLVM-IR for the file");
app.add_flag("-s", isAOT, "Compile XSharp into executable");
app.add_option("Input files", inputFiles, "Input files to compile")->required();
app.add_option("Input files", inputFiles, "Input files to compile")
->required();
app.add_option("-o", defaultOutputName, "Where to put the executable");

CLI11_PARSE(app, argc, argv);
Expand All @@ -41,8 +41,7 @@ int main(int argc, char *argv[])
projectPath.subString(0, projectPath.lastSubStringIndex("/") + 1);
projectPath.append("../");

if (isAOT)
return compile(inputFiles[0].toStdString().c_str());
if (isAOT) return compile(inputFiles[0].toStdString().c_str());

return 0;
}
Expand Down Expand Up @@ -80,12 +79,12 @@ int compile(const char *path)
TypeAdapter::setLLVMContext(&helper.ctx.llvm_ctx);

if (emitLLVMIR) {
helper.generateTextIR(ast.get(), XString(path).append(".ll"));
helper.generateTextIR(ast.get(), defaultOutputName);
return 0;
} else {
helper.generateIR(ast.get(), XString(path).append(".bc"));
}

helper.generateIR(ast.get(), XString(path).append(".bc"));

if (!helper.ctx._errors.empty()) {
fmt::print("Semantic error in {}:\n", path);
for (auto error : helper.ctx._errors)
Expand All @@ -96,8 +95,7 @@ int compile(const char *path)
auto object_path = XString(path).append(".o");

auto error_code = emit_object_code(object_path, helper.ctx.module);
if (error_code.value() != 0)
std::cout << error_code.message();
if (error_code.value() != 0) std::cout << error_code.message();

if (!hasDefaultOutputName) {
if (XString(path).lastSubStringIndex("xsharp") ==
Expand Down
13 changes: 0 additions & 13 deletions buildTest.sh

This file was deleted.

6 changes: 3 additions & 3 deletions test/update-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
xsharpc_path = os.path.join(bin_path, "xsharpc")

# update LLVM-IR
path = os.path.join(project_path, "LLVMIR/test")
files = os.listdir(path)
llvm_test_path = os.path.join(project_path, "LLVMIR", "test")
files = os.listdir(llvm_test_path)
for file in files:
file_path = os.path.join(path, file)
file_path = os.path.join(llvm_test_path, file)

if file.endswith(".xsharp"):
os.popen(xsharpc_path + " --emit-llvm-ir " + file_path)
Expand Down
60 changes: 52 additions & 8 deletions test/xsharp-test.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,66 @@
#!/usr/bin/env python3

import argparse
import difflib
import os

parser = argparse.ArgumentParser();
parser = argparse.ArgumentParser()
allgroup = parser.add_mutually_exclusive_group()
parser.add_argument_group()

parser.add_argument('-v', '--verbose', help="Print test information in detail", action="store_false")

allgroup.add_argument('-a', '--all', help="Test all testsuites", action="store_true")
allgroup.add_argument('--ast', help="Test generating AST", action="store_false"),
allgroup.add_argument('--llvm', help="Test generating LLVM-IR", action="store_false"),
allgroup.add_argument('--java', help="Test generating Java bytecode (Not supported)", action="store_true")
parser.add_argument(
"-v", "--verbose", help="Print test information in detail", action="store_true"
)
allgroup.add_argument("-a", "--all", help="Test all testsuites", action="store_true")
allgroup.add_argument("--ast", help="Test generating AST", action="store_false"),
allgroup.add_argument("--llvm", help="Test generating LLVM-IR", action="store_false"),
allgroup.add_argument(
"--java", help="Test generating Java bytecode (Not supported)", action="store_true"
)

args = parser.parse_args()

project_path = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0]
bin_path = os.path.join(project_path, "bin")
xsharpc_path = os.path.join(bin_path, "xsharpc")

total_test = 0
failure_test = 0

# Test LLVM-IR generation
llvm_test_path = os.path.join(project_path, "LLVMIR/test")
files = os.listdir(llvm_test_path)

for file in files:
file_path = os.path.join(llvm_test_path, file)

if file.endswith(".xsharp"):
source_path = file_path
ir_path = file_path + ".ll"
total_test += 1

with open(source_path, mode="r") as source:
os.makedirs(os.path.join(llvm_test_path, "temp"), exist_ok=True)
temp_path = os.path.join(llvm_test_path, "temp", file + ".ll")
os.popen(xsharpc_path + " --emit-llvm-ir " + file_path + " -o " + temp_path)

with open(temp_path, mode="r") as temp:
temp_lines = temp.readlines()

with open(ir_path, mode="r") as ir:
ir_lines = ir.readlines()

if ir_lines != temp_lines:
failure_test += 1
print("[{}] Test failed at {}:".format(total_test,source_path))

if args.verbose:
print(''.join(list(difflib.ndiff(ir_lines, temp_lines))))
else:
print("[{}] Test passed {}:".format(total_test,source_path))

print(project_path)

print("===================Test Completed=======================")
print("Total {} tests".format(total_test))
print("Passed {} tests".format(total_test - failure_test))
print("Failed {} tests".format(failure_test))

0 comments on commit cd5c956

Please sign in to comment.