Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for LLVM bindings #472

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ jobs:
- name: Run Test target
# if: github.event_name != 'pull_request'
env:
LLVM_LIB_DIR: /home/runner/work/spice/llvm/build/lib
LLVM_INCLUDE_DIR: /home/runner/work/spice/llvm/llvm/include
LLVM_BUILD_INCLUDE_DIR: /home/runner/work/spice/llvm/build/include
SPICE_STD_DIR: /home/runner/work/spice/spice/std
SPICE_BOOTSTRAP_DIR: /home/runner/work/spice/spice/src-bootstrap
run: |
Expand All @@ -112,6 +115,9 @@ jobs:
# - name: Run Test target with Valgrind
# if: github.event_name == 'pull_request'
# env:
# LLVM_LIB_DIR: /home/runner/work/spice/llvm/build/lib
# LLVM_INCLUDE_DIR: /home/runner/work/spice/llvm/llvm/include
# LLVM_BUILD_INCLUDE_DIR: /home/runner/work/spice/llvm/build/include
# SPICE_STD_DIR: /home/runner/work/spice/spice/std
# SPICE_BOOTSTRAP_DIR: /home/runner/work/spice/spice/src-bootstrap
# run: |
Expand Down
7 changes: 4 additions & 3 deletions .run/spice.run.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="spice" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="build -d -O2 -ir ../../media/test-project/test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spice" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spice">
<configuration default="false" name="spice" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -d -O2 -ir ../../media/test-project/test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spice" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spice">
<envs>
<env name="LLVM_LIB_DIR" value="D:/LLVM/build-release/lib" />
<env name="LLVM_INCLUDE_DIR" value="D:/LLVM/llvm/include" />
<env name="LLVM_BUILD_INCLUDE_DIR" value="D:/LLVM/build-release/include" />
<env name="LLVM_INCLUDE_DIR" value="D:/LLVM/llvm/include" />
<env name="LLVM_LIB_DIR" value="D:/LLVM/build-release/lib" />
<env name="LLVM_ADDITIONAL_FLAGS" value="-lole32 -lws2_32" />
<env name="SPICE_STD_DIR" value="$PROJECT_DIR$/std" />
</envs>
<method v="2">
Expand Down
6 changes: 5 additions & 1 deletion .run/spicetest.run.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="spicetest" type="CMakeGoogleTestRunConfigurationType" factoryName="Google Test" PROGRAM_PARAMS="--update-refs=false" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spicetest" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spicetest" TEST_MODE="SUITE_TEST">
<configuration default="false" name="spicetest" type="CMakeGoogleTestRunConfigurationType" factoryName="Google Test" PROGRAM_PARAMS="--update-refs=false" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spicetest" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spicetest" TEST_CLASS="BootstrapCompilerTests" TEST_MODE="SUITE_TEST">
<envs>
<env name="LLVM_BUILD_INCLUDE_DIR" value="D:/LLVM/build-release/include" />
<env name="LLVM_INCLUDE_DIR" value="D:/LLVM/llvm/include" />
<env name="LLVM_LIB_DIR" value="D:/LLVM/build-release/lib" />
<env name="RUN_TESTS" value="ON" />
<env name="LLVM_ADDITIONAL_FLAGS" value="-lole32 -lws2_32" />
<env name="SPICE_STD_DIR" value="$PROJECT_DIR$/std" />
</envs>
<method v="2">
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/language/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ For attributes of type bool, the value `true` can be omitted.

### Available attributes
- `core.linker.flag: string (default: "")`: Append linker flag
- `core.linux.linker.flag: string (default: "")`: Append linker flag for Linux
- `core.windows.linker.flag: string (default: "")`: Append linker flag for Windows
- `core.compiler.alwaysKeepOnNameCollision: bool (default: false)`: Always keep the symbols of this source files when merging the name registries of multiple source files


Expand Down
66 changes: 49 additions & 17 deletions media/test-project/test.spice
Original file line number Diff line number Diff line change
@@ -1,22 +1,54 @@
type Struct struct {
int _fieldA
bool _fieldB
string _fieldC
}
import "bootstrap/bindings/llvm/llvm" as llvm;
import "std/data/vector";

f<int> main() {
printf("Alignment of double: %d\n", alignof(-19.34989));
printf("Alignment of int: %d\n", alignof(353));
printf("Alignment of short: %d\n", alignof(35s));
printf("Alignment of long: %d\n", alignof(9223372036854775807l));
printf("Alignment of byte: %d\n", alignof((byte) 13));
printf("Alignment of char: %d\n", alignof((char) 65));
printf("Alignment of string: %d\n", alignof("Hello Spice!"));
printf("Alignment of bool: %d\n", alignof(false));
printf("Alignment of int[]: %d\n", alignof([1, 2, 3, 4, 5, 6, 7]));
int intVariable = 123;
printf("Alignment of int*: %d\n", alignof(&intVariable));
printf("Alignment of struct instance: %d\n", alignof(type Struct));
llvm::initializeNativeTarget();
llvm::initializeNativeAsmPrinter();

heap string targetTriple = llvm::getDefaultTargetTriple();
string error;
llvm::Target target = llvm::getTargetFromTriple(targetTriple, &error);
llvm::TargetMachine targetMachine = target.createTargetMachine(targetTriple, "generic", "", llvm::LLVMCodeGenOptLevel::CodeGenLevelDefault, llvm::LLVMRelocMode::RelocDefault, llvm::LLVMCodeModel::CodeModelDefault);

llvm::LLVMContext context;
llvm::Module module = llvm::Module("test", context);
module.setDataLayout(targetMachine.createDataLayout());
module.setTargetTriple(targetTriple);
llvm::Builder builder = llvm::Builder(context);

llvm::Type returnType = builder.getInt32Ty();
Vector<llvm::Type> argTypes;
llvm::Type funcType = llvm::getFunctionType(returnType, argTypes);
llvm::Function func = llvm::Function(module, "main", funcType);
func.setLinkage(llvm::LLVMLinkage::ExternalLinkage);

llvm::BasicBlock entry = llvm::BasicBlock(context, "");
func.pushBack(entry);
builder.setInsertPoint(entry);

llvm::Value calcResult = builder.createAdd(builder.getInt32(1), builder.getInt32(2), "calcResult");

llvm::Value helloWorldStr = builder.createGlobalStringPtr("Hello, world!\n", "helloWorldStr");
Vector<llvm::Type> printfArgTypes;
printfArgTypes.pushBack(builder.getPtrTy());
printfArgTypes.pushBack(builder.getInt32Ty());
llvm::Type printfFuncType = llvm::getFunctionType(builder.getInt32Ty(), printfArgTypes, true);
llvm::Function printfFunc = module.getOrInsertFunction("printf", printfFuncType);

Vector<llvm::Value> printfArgs;
printfArgs.pushBack(helloWorldStr);
printfArgs.pushBack(calcResult);
builder.createCall(printfFunc, printfArgs);

builder.createRet(builder.getInt32(0));

assert !llvm::verifyFunction(func);
string output;
assert !llvm::verifyModule(module, &output);

printf("%s", module.print());

//llvm::PassBuilderOptions passBuilderOptions;
}

/*import "bootstrap/util/block-allocator";
Expand Down
22 changes: 15 additions & 7 deletions src-bootstrap/bindings/llvm/linker-flags.spice
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
#![
// Paths - Linux
core.linker.flag = "-L$LLVM_LIB_DIR",
core.linker.flag = "-I$LLVM_INCLUDE_DIR",
core.linker.flag = "-I$LLVM_BUILD_INCLUDE_DIR",
core.linux.linker.flag = "-L$LLVM_LIB_DIR",
core.linux.linker.flag = "-I$LLVM_INCLUDE_DIR",
core.linux.linker.flag = "-I$LLVM_BUILD_INCLUDE_DIR",
core.linux.linker.flag = "-lm", // math
core.linux.linker.flag = "-lz", // zlib
core.linux.linker.flag = "-ltinfo", // ncurses
core.linux.linker.flag = "-lzstd", // zstd
// Paths - Windows
core.linker.flag = "-L%LLVM_LIB_DIR%", // e.g.: D:/LLVM/build-release/lib
core.linker.flag = "-I%LLVM_INCLUDE_DIR%", // e.g.: D:/LLVM/llvm/include
core.linker.flag = "-I%LLVM_BUILD_INCLUDE_DIR%", // e.g.: D:/LLVM/build-release/include
core.windows.linker.flag = "-L%LLVM_LIB_DIR%", // e.g.: D:/LLVM/build-release/lib
core.windows.linker.flag = "-I%LLVM_INCLUDE_DIR%", // e.g.: D:/LLVM/llvm/include
core.windows.linker.flag = "-I%LLVM_BUILD_INCLUDE_DIR%", // e.g.: D:/LLVM/build-release/include
core.windows.linker.flag = "-lole32", // COM
core.windows.linker.flag = "-lws2_32", // WinSock
// LLVM libs
core.linker.flag = "-lLLVMAArch64AsmParser",
core.linker.flag = "-lLLVMAArch64CodeGen",
Expand Down Expand Up @@ -83,7 +89,9 @@
core.linker.flag = "-lLLVMExegesisX86",
core.linker.flag = "-lLLVMExtensions",
core.linker.flag = "-lLLVMFileCheck",
core.linker.flag = "-lLLVMFrontendDriver",
core.linker.flag = "-lLLVMFrontendHLSL",
core.linker.flag = "-lLLVMFrontendOffloading",
core.linker.flag = "-lLLVMFrontendOpenACC",
core.linker.flag = "-lLLVMFrontendOpenMP",
core.linker.flag = "-lLLVMFuzzerCLI",
Expand All @@ -94,6 +102,7 @@
core.linker.flag = "-lLLVMHexagonDesc",
core.linker.flag = "-lLLVMHexagonDisassembler",
core.linker.flag = "-lLLVMHexagonInfo",
core.linker.flag = "-lLLVMHipStdPar",
core.linker.flag = "-lLLVMInstCombine",
core.linker.flag = "-lLLVMInstrumentation",
core.linker.flag = "-lLLVMInterfaceStub",
Expand Down Expand Up @@ -205,7 +214,6 @@
core.linker.flag = "-lLLVMXCoreInfo",
core.linker.flag = "-lLLVMXRay",
core.linker.flag = "-lstdc++",
core.linker.flag = "-lole32",
core.linker.flag = "-luuid",
core.linker.flag = "-pthread",
// Wrapper around target macro definitions
Expand Down
16 changes: 16 additions & 0 deletions src/ast/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace spice::compiler {

// Constants
static constexpr const char *const ATTR_CORE_LINKER_FLAG = "core.linker.flag";
static constexpr const char *const ATTR_CORE_LINUX_LINKER_FLAG = "core.linux.linker.flag";
static constexpr const char *const ATTR_CORE_WINDOWS_LINKER_FLAG = "core.windows.linker.flag";
static constexpr const char *const ATTR_CORE_LINKER_ADDITIONAL_SOURCE = "core.linker.additional_source";
static constexpr const char *const ATTR_CORE_LINKER_DLL = "core.linker.dll";
static constexpr const char *const ATTR_CORE_COMPILER_MANGLE = "core.compiler.mangle";
Expand Down Expand Up @@ -42,6 +44,20 @@ static const std::unordered_map<std::string, AttrConfigValue> ATTR_CONFIGS = {
.type = AttrNode::TYPE_STRING,
},
},
{
ATTR_CORE_LINUX_LINKER_FLAG,
{
.target = AttrNode::TARGET_MODULE,
.type = AttrNode::TYPE_STRING,
},
},
{
ATTR_CORE_WINDOWS_LINKER_FLAG,
{
.target = AttrNode::TARGET_MODULE,
.type = AttrNode::TYPE_STRING,
},
},
{
ATTR_CORE_LINKER_ADDITIONAL_SOURCE,
{
Expand Down
18 changes: 15 additions & 3 deletions src/symboltablebuilder/SymbolTableBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,11 +624,23 @@ std::any SymbolTableBuilder::visitModAttr(ModAttrNode *node) {
// Retrieve attributes
const AttrLstNode *attrs = node->attrLst();

// Collect linker flags
std::vector<const CompileTimeValue *> linkerFlagValues;
// core.linker.flag
for (const CompileTimeValue *value : attrs->getAttrValuesByName(ATTR_CORE_LINKER_FLAG)) {
const std::string &stringValue = resourceManager.compileTimeStringValues.at(value->stringValueOffset);
resourceManager.linker.addLinkerFlag(stringValue);
std::vector<const CompileTimeValue *> values = attrs->getAttrValuesByName(ATTR_CORE_LINKER_FLAG);
linkerFlagValues.insert(linkerFlagValues.end(), values.begin(), values.end());
// core.linux.linker.flag
if (resourceManager.targetMachine->getTargetTriple().isOSLinux()) {
values = attrs->getAttrValuesByName(ATTR_CORE_LINUX_LINKER_FLAG);
linkerFlagValues.insert(linkerFlagValues.end(), values.begin(), values.end());
}
// core.windows.linker.flag
if (resourceManager.targetMachine->getTargetTriple().isOSWindows()) {
values = attrs->getAttrValuesByName(ATTR_CORE_WINDOWS_LINKER_FLAG);
linkerFlagValues.insert(linkerFlagValues.end(), values.begin(), values.end());
}
for (const CompileTimeValue *value : linkerFlagValues)
resourceManager.linker.addLinkerFlag(resourceManager.compileTimeStringValues.at(value->stringValueOffset));

// core.linker.additional_source
for (const CompileTimeValue *value : attrs->getAttrValuesByName(ATTR_CORE_LINKER_ADDITIONAL_SOURCE)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
; ModuleID = 'test'
source_filename = "test"

@helloWorldStr = private unnamed_addr constant [15 x i8] c"Hello, world!\0A\00", align 1

define i32 @main() {
%1 = call i32 (ptr, i32, ...) @printf(ptr @helloWorldStr, i32 3)
ret i32 0
}

declare i32 @printf(ptr, i32, ...)
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import "bootstrap/bindings/llvm/llvm" as llvm;
import "std/data/vector";

f<int> main() {
llvm::initializeNativeTarget();
llvm::initializeNativeAsmPrinter();

heap string targetTriple = llvm::getDefaultTargetTriple();
string error;
llvm::Target target = llvm::getTargetFromTriple(targetTriple, &error);
llvm::TargetMachine targetMachine = target.createTargetMachine(targetTriple, "generic", "", llvm::LLVMCodeGenOptLevel::CodeGenLevelDefault, llvm::LLVMRelocMode::RelocDefault, llvm::LLVMCodeModel::CodeModelDefault);

llvm::LLVMContext context;
llvm::Module module = llvm::Module("test", context);
module.setDataLayout(targetMachine.createDataLayout());
//module.setTargetTriple(targetTriple); // This emits target dependent information in the IR, which is not what we want here.
llvm::Builder builder = llvm::Builder(context);

llvm::Type returnType = builder.getInt32Ty();
Vector<llvm::Type> argTypes;
llvm::Type funcType = llvm::getFunctionType(returnType, argTypes);
llvm::Function func = llvm::Function(module, "main", funcType);
func.setLinkage(llvm::LLVMLinkage::ExternalLinkage);

llvm::BasicBlock entry = llvm::BasicBlock(context, "");
func.pushBack(entry);
builder.setInsertPoint(entry);

llvm::Value calcResult = builder.createAdd(builder.getInt32(1), builder.getInt32(2), "calcResult");

llvm::Value helloWorldStr = builder.createGlobalStringPtr("Hello, world!\n", "helloWorldStr");
Vector<llvm::Type> printfArgTypes;
printfArgTypes.pushBack(builder.getPtrTy());
printfArgTypes.pushBack(builder.getInt32Ty());
llvm::Type printfFuncType = llvm::getFunctionType(builder.getInt32Ty(), printfArgTypes, true);
llvm::Function printfFunc = module.getOrInsertFunction("printf", printfFuncType);

Vector<llvm::Value> printfArgs;
printfArgs.pushBack(helloWorldStr);
printfArgs.pushBack(calcResult);
builder.createCall(printfFunc, printfArgs);

builder.createRet(builder.getInt32(0));

assert !llvm::verifyFunction(func);
string output;
assert !llvm::verifyModule(module, &output);

printf("%s", module.print());
}