Skip to content

Commit

Permalink
Extend bootstrap compiler (#569)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer authored May 26, 2024
1 parent 65847f5 commit ccaa8fa
Show file tree
Hide file tree
Showing 14 changed files with 943 additions and 229 deletions.
492 changes: 408 additions & 84 deletions src-bootstrap/ast/ast-nodes.spice

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src-bootstrap/bindings/llvm/llvm.spice
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,6 @@ public p getVersion(unsigned int* major, unsigned int* minor, unsigned int* patc
LLVMGetVersion(major, minor, patch);
}

public p shutdown() {
public p llvm_shutdown() {
LLVMShutdown();
}
20 changes: 10 additions & 10 deletions src-bootstrap/compiler-pass.spice
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
// Own imports
import "bootstrap/global/global-resource-manager";
import "bootstrap/global/global-resource-manager-intf";
import "bootstrap/driver";
import "bootstrap/source-file";
import "bootstrap/source-file-intf";
import "bootstrap/symboltablebuilder/scope";

type CompilerPass struct {
GlobalResourceManager& resourceManager
const CliOptions& cliOptions
SourceFile* sourceFile
IGlobalResourceManager& resourceManager
CliOptions& cliOptions
ISourceFile* sourceFile
heap Scope* rootScope
unsigned long manIdx = 0l
Scope* currentScope
}

p CompilerPass.ctor(GlobalResourceManager& resourceManager, SourceFile* sourceFile = nil<SourceFile*>) {
p CompilerPass.ctor(IGlobalResourceManager& resourceManager, ISourceFile* sourceFile = nil<ISourceFile*>) {
this.resourceManager = resourceManager;
this.cliOptions = resourceManager.cliOptions;
this.sourceFile = sourceFile;
this.rootScope = sourceFile != nil<SourceFile*> ? sourceFile.globalScope : nil<heap Scope*>;
this.currentScope = (Scope*) this.rootScope;
this.rootScope = sourceFile != nil<ISourceFile*> ? sourceFile.globalScope : nil<heap Scope*>;
this.currentScope = sNonOwned(this.rootScope);
}

/**
Expand All @@ -32,7 +32,7 @@ p CompilerPass.ctor(GlobalResourceManager& resourceManager, SourceFile* sourceFi
p CompilerPass.changeToScope(Scope* scope, ScopeType scopeType) {
assert scope != nil<Scope*>;
assert scope.scopeType == scopeType;
assert !script.isGenericScope;
assert !scope.isGenericScope;
// Adjust members of the new scope
scope.parent = this.currentScope;
scope.symbolTable.parent = &this.currentScope.symbolTable;
Expand All @@ -47,7 +47,7 @@ p CompilerPass.changeToScope(Scope* scope, ScopeType scopeType) {
* @param scopeType Expected type of the given scope
*/
p CompilerPass.changeToScope(const String& scopeName, ScopeType scopeType) {
assert !scopeName.isEmtpy();
assert !scopeName.isEmpty();
this.changeToScope(this.currentScope.getChildScope(scopeName), scopeType);
}

Expand Down
8 changes: 4 additions & 4 deletions src-bootstrap/driver.spice
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import "std/io/cli-option";
import "std/io/filepath";

// Constants
const string TARGET_UNKNOWN = "unknown";
const string TARGET_WASM32 = "wasm32";
const string TARGET_WASM64 = "wasm64";
const string ENV_VAR_DOCKERIZED = "SPICE_DOCKERIZED";
public const string TARGET_UNKNOWN = "unknown";
public const string TARGET_WASM32 = "wasm32";
public const string TARGET_WASM64 = "wasm64";
public const string ENV_VAR_DOCKERIZED = "SPICE_DOCKERIZED";

public type OptLevel enum {
O0 = 0, // No optimization
Expand Down
4 changes: 2 additions & 2 deletions src-bootstrap/global/cache-manager.spice
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import "std/io/filepath";
import "bootstrap/source-file";

public type CacheManager struct {
const FilePath &cacheDir
FilePath &cacheDir
}

public p CacheManager.ctor(const FilePath &cacheDir) {
public p CacheManager.ctor(FilePath &cacheDir) {
this.cacheDir = cacheDir;
}

Expand Down
36 changes: 14 additions & 22 deletions src-bootstrap/global/global-resource-manager.spice
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public type GlobalResourceManager struct : IGlobalResourceManager {
public BlockAllocator<ASTNode> astNodeAlloc // Used to allocate all AST nodes
public UnorderedMap<String, heap SourceFile*> sourceFiles // The GlobalResourceManager owns all source files
public Vector<ASTNode*> astNodes
public const CliOptions& cliOptions
public CliOptions& cliOptions
public ExternalLinkerInterface linker
public CacheManager cacheManager
public RuntimeModuleManager runtimeModuleManager
Expand All @@ -48,7 +48,7 @@ public type GlobalResourceManager struct : IGlobalResourceManager {
unsigned long nextCustomTypeId = BYTE_MAX_VALUE + 1l // Start at 256 because all primitive types come first
}

public p GlobalResourceManager.ctor(const CliOptions& cliOptions) {
public p GlobalResourceManager.ctor(CliOptions& cliOptions) {
this.cliOptions = cliOptions;
this.builder = llvm::IRBuilder(this.context);
this.astNodeAlloc = BlockAllocator<ASTNode>(this.memoryManager);
Expand All @@ -63,25 +63,18 @@ public p GlobalResourceManager.ctor(const CliOptions& cliOptions) {
llvm::initializeAllAsmPrinters();
}

// Search after selected target
String error;
// ToDo: Lookup target

// Create target machine for LLVM
String cpuName = String("generic");
if cliOptions.isNativeTarget & cliOptions.usesCPUFeatures {
if cliOptions.isNativeTarget & cliOptions.useCPUFeatures {
// Retrieve native CPU name and the supported CPU features
cpuName = llvm::sys::getHostCPUName();
cpuName = String(llvm::getHostCPUName());

}

// Create target machine
this.targetMachine = target.createTargetMachine(cpuName, cpuName.getRaw(), "", opt, llvm::Reloc::PIC_);

// Create lto module
if cliOptions.useLTO {
this.ltoModule = llvm::Module(LTO_FILE_NAME, context);
}
if cliOptions.useLTO {
this.ltoModule = llvm::Module(LTO_FILE_NAME, this.context);
}
}

public p GlobalResourceManager.dtor() {
Expand All @@ -93,10 +86,10 @@ public p GlobalResourceManager.dtor() {

public f<heap SourceFile*> GlobalResourceManager.createSourceFile(SourceFile* parent, const String& depName, const FilePath& path, bool isStdFile) {
// Check if the source file was already added (e.g. by another source file that imports it)
const String filePathStr = path.toString();
const String filePathStr = String(path.toString());

// Create the new source file if it does not exist yet
if !sourceFiles.contains(filePathStr) {
if !this.sourceFiles.contains(filePathStr) {
//heap SourceFile* newSourceFile = new SourceFile(*this, parent, depName, path, isStdFile);
//this.sourceFiles.insert(filePathStr, newSourceFile);
}
Expand All @@ -105,13 +98,12 @@ public f<heap SourceFile*> GlobalResourceManager.createSourceFile(SourceFile* pa
}

public f<unsigned long> GlobalResourceManager.getNextCustomTypeId() {
return nextCustomTypeId++;
return this.nextCustomTypeId++;
}

public f<unsigned long> GlobalResourceManager.getTotalLineCount() {
unsigned long totalLineCount = 0l;
foreach const SourceFile* sourceFile : sourceFiles {
totalLineCount += sourceFile.value.getLineCount();
}
return totalLineCount;
result = 0l;
/*foreach const SourceFile* sourceFile : sourceFiles {
result += sourceFile.value.getLineCount();
}*/
}
41 changes: 21 additions & 20 deletions src-bootstrap/global/runtime-module-manager.spice
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import "std/data/unordered-map";

// Own imports
import "bootstrap/source-file";
import "bootstrap/source-file-intf";
import "bootstrap/util/file-util";
import "bootstrap/global/global-resource-manager-intf";

// Constants
const string STRING_RT_IMPORT_NAME = "__rt_string";
const string RESULT_RT_IMPORT_NAME = "__rt_result";
const string ERROR_RT_IMPORT_NAME = "__rt_error";
Expand All @@ -16,8 +17,8 @@ public type RuntimeModule enum {
STRING_RT = 1,
RESULT_RT = 2,
ERROR_RT = 4,
MEMORY_RT = 8,
RTTI_RT = 16
MEMORY_RT = 8,
RTTI_RT = 16
}

type ModuleNamePair struct {
Expand All @@ -27,24 +28,24 @@ type ModuleNamePair struct {

public type RuntimeModuleManager struct {
IGlobalResourceManager &resourceManager
UnorderedMap<RuntimeModule, SourceFile *> modules
UnorderedMap<RuntimeModule, ISourceFile *> modules
}

public p RuntimeModuleManager.ctor(IGlobalResourceManager &resourceManager) {
this.resourceManager = resourceManager;
}

public f<SourceFile *> RuntimeModuleManager.requestModule(SourceFile* parentSourceFile, RuntimeModule requestedModule) {
const string importName = resolveNamePair(requestedModule).importName;
public f<ISourceFile *> RuntimeModuleManager.requestModule(ISourceFile* parentSourceFile, RuntimeModule requestedModule) {
const String importName = String(this.resolveNamePair(requestedModule).importName);

// Check if the requested module is available already, if not load it
dyn rtFile = isModuleAvailable(requestedModule) ? getModule(requestedModule) : loadModule(parentSourceFile, requestedModule);
dyn rtFile = this.isModuleAvailable(requestedModule) ? this.getModule(requestedModule) : this.loadModule(parentSourceFile, requestedModule);

// Add the dependency to the parent source file
parentSourceFile.addDependency(rtFile, parentSourceFile.ast, importName, rtFile.filePath.str());
parentSourceFile.addDependency(rtFile, parentSourceFile.ast, importName, rtFile.filePath.toString());
assert parentSourceFile.dependencies.contains(importName);
SourceFile* runtimeFile = parentSourceFile.dependencies.get(importName);
modules.insert(requestedModule, runtimeFile);
ISourceFile* runtimeFile = parentSourceFile.dependencies.get(importName);
this.modules.upsert(requestedModule, runtimeFile);

// Merge the module name registry with the one of the source file
parentSourceFile.mergeNameRegistries(*rtFile, importName);
Expand All @@ -55,22 +56,22 @@ public f<SourceFile *> RuntimeModuleManager.requestModule(SourceFile* parentSour
return runtimeFile;
}

public f<SourceFile *> RuntimeModuleManager.getModule(RuntimeModule requestedModule) {
assert modules.contains(requestedModule);
return modules.get(requestedModule);
public f<ISourceFile *> RuntimeModuleManager.getModule(RuntimeModule requestedModule) {
assert this.modules.contains(requestedModule);
return this.modules.get(requestedModule);
}

public f<bool> RuntimeModuleManager.isModuleAvailable(RuntimeModule requestedModule) {
return modules.contains(requestedModule);
return this.modules.contains(requestedModule);
}

public f<SourceFile *> RuntimeModuleManager.loadModule(SourceFile* parentSourceFile, RuntimeModule requestedModule) {
const ModuleNamePair namePair = resolveNamePair(requestedModule);
const string filePath = getStdDir() / "runtime" / fileName / ".spice";
public f<ISourceFile *> RuntimeModuleManager.loadModule(ISourceFile* parentSourceFile, RuntimeModule requestedModule) {
const ModuleNamePair namePair = this.resolveNamePair(requestedModule);
const FilePath filePath = getStdDir() / "runtime" / namePair.fileName / ".spice";
assert filePath != parentSourceFile.filePath;

// Instruct the global resource manager to create a new source file
SourceFile* moduleSourceFile = resourceManager.createSourceFile(parentSourceFile, importName, filrPath, true);
SourceFile* moduleSourceFile = this.resourceManager.createSourceFile(parentSourceFile, namePair.importName, filePath, true);
moduleSourceFile.isMainFile = false;

// Run frontend and first type checker run for the loaded source file
Expand All @@ -91,10 +92,10 @@ public f<ModuleNamePair> RuntimeModuleManager.resolveNamePair(RuntimeModule requ
case RuntimeModule::ERROR_RT: {
return ModuleNamePair{ERROR_RT_IMPORT_NAME, "error_rt"};
}
case RuntimeModule::ARRAY_RT: {
case RuntimeModule::MEMORY_RT: {
return ModuleNamePair{MEMORY_RT_IMPORT_NAME, "memory_rt"};
}
case RuntimeModule::OBJECT_RT: {
case RuntimeModule::RTTI_RT: {
return ModuleNamePair{RTTI_RT_IMPORT_NAME, "rtti_rt"};
}
default: {
Expand Down
23 changes: 16 additions & 7 deletions src-bootstrap/linker/external-linker-interface.spice
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import "bootstrap/driver";
public type ExternalLinkerInterface struct {
CliOptions& cliOptions
public FilePath outputPath
Vector<string> objectFilePaths
Vector<string> linkerFlags
Vector<FilePath> objectFilePaths
Vector<String> linkerFlags
}

public p ExternalLinkerInterface.ctor(const CliOptions& cliOptions) {
public p ExternalLinkerInterface.ctor(CliOptions& cliOptions) {
this.cliOptions = cliOptions;
this.outputPath = cliOptions.outputPath;
}
Expand Down Expand Up @@ -43,7 +43,6 @@ public p ExternalLinkerInterface.prepare() {
* Start the linking process
*/
public p ExternalLinkerInterface.link() {
assert !this.outputPath.isEmpty();

// ToDo
}
Expand All @@ -53,7 +52,7 @@ public p ExternalLinkerInterface.link() {
*
* @param objectFilePath Path to the object file
*/
public p ExternalLinkerInterface.addObjectFilePath(string objectFilePath) {
public p ExternalLinkerInterface.addObjectFilePath(const FilePath& objectFilePath) {
this.objectFilePaths.pushBack(objectFilePath);
}

Expand All @@ -63,6 +62,15 @@ public p ExternalLinkerInterface.addObjectFilePath(string objectFilePath) {
* @param linkerFlag Linker flag
*/
public p ExternalLinkerInterface.addLinkerFlag(string linkerFlag) {
this.linkerFlags.pushBack(String(linkerFlag));
}

/**
* Add another linker flag for the call to the linker executable
*
* @param linkerFlag Linker flag
*/
public p ExternalLinkerInterface.addLinkerFlag(const String& linkerFlag) {
this.linkerFlags.pushBack(linkerFlag);
}

Expand All @@ -74,9 +82,10 @@ public p ExternalLinkerInterface.addLinkerFlag(string linkerFlag) {
public p ExternalLinkerInterface.addAdditionalSourcePath(FilePath additionalSource) {
// Check if the file exists
if !additionalSource.exists() {
panic(Error("The additional source file '" + additionalSource.toGenericString() + "' does not exist"));
const String msg = "The additional source file '" + additionalSource.toGenericString() + "' does not exist";
panic(Error(msg.getRaw()));
}

// Add the file to the linker
this.addObjectFilePath(additionalSource.toNativeString());
this.addObjectFilePath(additionalSource);
}
11 changes: 7 additions & 4 deletions src-bootstrap/parser/parser.spice
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@
import "std/data/stack";

// Own imports
import "bootstrap/compiler-pass";
//import "bootstrap/compiler-pass";
import "bootstrap/lexer/lexer";
import "bootstrap/lexer/token";
import "bootstrap/ast/ast-nodes";
import "bootstrap/util/block-allocator";

// Generic types
type T dyn;

public type Parser struct {
compose CompilerPass compilerPass
//compose CompilerPass compilerPass
Lexer& lexer
Stack<ASTNode*> parentStack
BlockAllocator<ASTNode> astNodeAlloc // ToDo: Remove and use allocator from resource manager via compilerPass
}

public p Parser.ctor(Lexer& lexer) {
Expand All @@ -32,8 +34,9 @@ f<T*> Parser.createNode<T>() {
}

// Create the new node
T* node = this.resourceManager.astNodeAlloc.allocate<T>(this.lexer.getCodeLoc());
this.resourceManager.astNodes.pushBack(node);
//T* node = this.resourceManager.astNodeAlloc.allocate<T>(this.lexer.getCodeLoc());
T* node = this.astNodeAlloc.allocate(T(this.lexer.getCodeLoc()));
//this.resourceManager.astNodes.pushBack(node);

// If this is not the entry node, we need to add the new node to its parent
if !isRootNode {
Expand Down
2 changes: 1 addition & 1 deletion src-bootstrap/source-file-intf.spice
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
// Own imports

public type ISourceFile interface {

public f<unsigned long> getLineCount();
}
Loading

0 comments on commit ccaa8fa

Please sign in to comment.