Merge pull request #44 from birth-software/first-llvm-test
Pass first test with LLVM. Ditch C transpiler
This commit is contained in:
commit
6114f539f6
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@ -13,13 +13,8 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [
|
||||
ubuntu-latest,
|
||||
]
|
||||
runs-on: ${{ matrix.os }}
|
||||
build_and_test:
|
||||
runs-on: [ self-hosted, Linux, x64 ]
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout
|
||||
@ -29,4 +24,4 @@ jobs:
|
||||
with:
|
||||
version: master
|
||||
- name: Test
|
||||
run: ./ci.sh
|
||||
run: ./ci.sh ../todo_foo_debug_path ../../../../../dev/llvm-static-release-zen4-17.0.6/out/x86_64-linux-musl-native
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
834
bootstrap/backend/llvm.cpp
Normal file
834
bootstrap/backend/llvm.cpp
Normal file
@ -0,0 +1,834 @@
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/IR/DIBuilder.h"
|
||||
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
|
||||
#include "llvm/TargetParser/Host.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
||||
#include "lld/Common/CommonLinkerContext.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern "C" LLVMContext* NativityLLVMCreateContext()
|
||||
{
|
||||
auto* context = new LLVMContext();
|
||||
return context;
|
||||
}
|
||||
|
||||
extern "C" Module* NativityLLVMCreateModule(const char* name_ptr, size_t name_len, LLVMContext& context)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* module = new Module(name, context);
|
||||
return module;
|
||||
}
|
||||
|
||||
extern "C" IRBuilder<>* NativityLLVMCreateBuilder(LLVMContext& Context)
|
||||
{
|
||||
auto* builder = new IRBuilder<>(Context);
|
||||
return builder;
|
||||
}
|
||||
|
||||
extern "C" DIBuilder* NativityLLVMModuleCreateDebugInfoBuilder(Module& module)
|
||||
{
|
||||
DIBuilder* builder = new DIBuilder(module);
|
||||
return builder;
|
||||
}
|
||||
|
||||
extern "C" DIFile* NativityLLVMDebugInfoBuilderCreateFile(DIBuilder& builder, const char* filename_ptr, size_t filename_len, const char* directory_ptr, size_t directory_len)
|
||||
{
|
||||
auto filename = StringRef(filename_ptr, filename_len);
|
||||
auto directory = StringRef(directory_ptr, directory_len);
|
||||
auto* file = builder.createFile(filename, directory);
|
||||
return file;
|
||||
}
|
||||
|
||||
extern "C" DICompileUnit* NativityLLVMDebugInfoBuilderCreateCompileUnit(DIBuilder& builder, unsigned language, DIFile* file, const char* producer_ptr, size_t producer_len, bool is_optimized, const char* flags_ptr, size_t flags_len, unsigned runtime_version, const char* split_name_ptr, size_t split_name_len, DICompileUnit::DebugEmissionKind debug_emission_kind, uint64_t DWOId, bool split_debug_inlining, bool debug_info_for_profiling, DICompileUnit::DebugNameTableKind debug_name_table_kind, bool ranges_base_address, const char* sysroot_ptr, size_t sysroot_len, const char* sdk_ptr, size_t sdk_len)
|
||||
{
|
||||
auto producer = StringRef(producer_ptr, producer_len);
|
||||
auto flags = StringRef(flags_ptr, flags_len);
|
||||
auto split_name = StringRef(split_name_ptr, split_name_len);
|
||||
auto sysroot = StringRef(sysroot_ptr, sysroot_len);
|
||||
auto sdk = StringRef(sdk_ptr, sdk_len);
|
||||
auto* compile_unit = builder.createCompileUnit(language, file, producer, is_optimized, flags, runtime_version, split_name, debug_emission_kind, DWOId, split_debug_inlining, debug_info_for_profiling, debug_name_table_kind, ranges_base_address, sysroot, sdk);
|
||||
return compile_unit;
|
||||
}
|
||||
|
||||
extern "C" DISubprogram* NativityLLVMDebugInfoBuilderCreateFunction(DIBuilder& builder, DIScope* scope, const char* name_ptr, size_t name_len, const char* linkage_name_ptr, size_t linkage_name_len, DIFile* file, unsigned line_number, DISubroutineType* type, unsigned scope_line, DINode::DIFlags flags, DISubprogram::DISPFlags subprogram_flags, DISubprogram* declaration)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto linkage_name = StringRef(linkage_name_ptr, linkage_name_len);
|
||||
DITemplateParameterArray template_parameters = nullptr;
|
||||
DITypeArray thrown_types = nullptr;
|
||||
DINodeArray annotations = nullptr;
|
||||
StringRef target_function_name = "";
|
||||
|
||||
auto* function = builder.createFunction(scope, name, linkage_name, file, line_number, type, scope_line, flags, subprogram_flags, template_parameters, declaration, thrown_types, annotations, target_function_name);
|
||||
return function;
|
||||
}
|
||||
|
||||
extern "C" DISubroutineType* NativityLLVMDebugInfoBuilderCreateSubroutineType(DIBuilder& builder, DIType** parameter_types_ptr, size_t parameter_type_count, DINode::DIFlags flags, dwarf::CallingConvention calling_convention)
|
||||
{
|
||||
auto metadata_list = ArrayRef<Metadata*>(reinterpret_cast<Metadata**>( parameter_types_ptr), parameter_type_count);
|
||||
auto parameter_types = builder.getOrCreateTypeArray(metadata_list);
|
||||
auto* subroutine_type = builder.createSubroutineType(parameter_types, flags, calling_convention);
|
||||
return subroutine_type;
|
||||
}
|
||||
|
||||
extern "C" DILexicalBlock* NativityLLVMDebugInfoBuilderCreateLexicalBlock(DIBuilder& builder, DIScope* parent_scope, DIFile* parent_file, unsigned line, unsigned column)
|
||||
{
|
||||
assert(isa<DILocalScope>(parent_scope));
|
||||
auto* block = builder.createLexicalBlock(parent_scope, parent_file, line, column);
|
||||
return block;
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMBuilderSetCurrentDebugLocation(IRBuilder<>& builder, LLVMContext& context, unsigned line, unsigned column, DIScope* scope, Function* function)
|
||||
{
|
||||
auto debug_location = DILocation::get(context, line, column, scope);
|
||||
builder.SetCurrentDebugLocation(debug_location);
|
||||
}
|
||||
|
||||
extern "C" DILocalVariable* NativityLLVMDebugInfoBuilderCreateParameterVariable(DIBuilder& builder, DIScope* scope, const char* name_ptr, size_t name_len, unsigned argument_index, DIFile* file, unsigned line_number, DIType* type, bool always_preserve, DINode::DIFlags flags)
|
||||
{
|
||||
assert(isa<DILocalScope>(scope));
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* parameter_variable = builder.createParameterVariable(scope, name, argument_index, file, line_number, type, always_preserve, flags);
|
||||
return parameter_variable;
|
||||
}
|
||||
|
||||
extern "C" DILocalVariable* NativityLLVMDebugInfoBuilderCreateAutoVariable(DIBuilder& builder, DIScope* scope, const char* name_ptr, size_t name_len, DIFile* file, unsigned line_number, DIType* type, bool always_preserve, DINode::DIFlags flags, uint32_t alignment) // 0 means 1 << 0 (alignment of 1)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* auto_variable = builder.createAutoVariable(scope, name, file, line_number, type, always_preserve, flags, alignment);
|
||||
return auto_variable;
|
||||
}
|
||||
|
||||
extern "C" Instruction* NativityLLVMDebugInfoBuilderInsertDeclare(DIBuilder& builder, Value* pointer, DILocalVariable* local_variable, LLVMContext& context, unsigned line, unsigned column, DIScope* scope, BasicBlock* basic_block)
|
||||
{
|
||||
auto debug_location = DILocation::get(context, line, column, scope);
|
||||
auto* expression = builder.createExpression();
|
||||
auto* instruction = builder.insertDeclare(pointer, local_variable, expression, debug_location, basic_block);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
extern "C" DIType* NativityLLVMDebugInfoBuilderCreateBasicType(DIBuilder& builder, const char* name_ptr, size_t name_len, uint64_t bit_count, unsigned dwarf_encoding, DINode::DIFlags flags)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* type = builder.createBasicType(name, bit_count, dwarf_encoding, flags);
|
||||
return type;
|
||||
}
|
||||
|
||||
extern "C" DIDerivedType* NativityLLVMDebugInfoBuilderCreatePointerType(DIBuilder& builder, DIType* element_type, uint64_t pointer_bit_count, uint32_t alignment, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
std::optional<unsigned> DWARFAddressSpace = std::nullopt;
|
||||
DINodeArray annotations = nullptr;
|
||||
auto* pointer_type = builder.createPointerType(element_type, pointer_bit_count, alignment, DWARFAddressSpace, name, annotations);
|
||||
return pointer_type;
|
||||
}
|
||||
|
||||
extern "C" DICompositeType* NativityLLVMDebugInfoBuilderCreateStructType(DIBuilder& builder, DIScope* scope, const char* name_ptr, size_t name_len, DIFile* file, unsigned line_number, uint64_t bit_count, uint32_t alignment, DINode::DIFlags flags, DIType* derived_from, DIType** element_type_ptr, size_t element_type_count)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto type_array = ArrayRef<Metadata*>(reinterpret_cast<Metadata**>(element_type_ptr), element_type_count);
|
||||
|
||||
auto* struct_type = builder.createStructType(scope, name, file, line_number, bit_count, alignment, flags, derived_from, builder.getOrCreateArray(type_array));
|
||||
return struct_type;
|
||||
}
|
||||
|
||||
extern "C" DICompositeType* NativityLLVMDebugInfoBuilderCreateArrayType(DIBuilder& builder, uint64_t bit_size, uint32_t alignment, DIType* type, size_t element_count)
|
||||
{
|
||||
Metadata* subranges[1] = {
|
||||
builder.getOrCreateSubrange(0, element_count),
|
||||
};
|
||||
DINodeArray subscripts = builder.getOrCreateArray(ArrayRef<Metadata*>(subranges, sizeof(subranges) / sizeof(subranges[0])));
|
||||
|
||||
auto* array_type = builder.createArrayType(bit_size, alignment, type, subscripts);
|
||||
return array_type;
|
||||
}
|
||||
|
||||
extern "C" DIEnumerator* NativityLLVMDebugInfoBuilderCreateEnumerator(DIBuilder& builder, const char* name_ptr, size_t name_len, uint64_t value, bool is_unsigned)
|
||||
{
|
||||
|
||||
// DIEnumerator *DIBuilder::createEnumerator(StringRef Name, uint64_t Val,
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* enumerator = builder.createEnumerator(name, value, is_unsigned);
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
extern "C" DICompositeType* NativityLLVMDebugInfoBuilderCreateEnumerationType(DIBuilder& builder, DIScope* scope, const char* name_ptr, size_t name_len, DIFile* file, unsigned line, uint64_t bit_size, uint32_t alignment, DIEnumerator** enumerator_ptr, size_t enumerator_count, DIType* underlying_type)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
DINodeArray enumerators = builder.getOrCreateArray(ArrayRef<Metadata*>(reinterpret_cast<Metadata**>(enumerator_ptr), enumerator_count));
|
||||
auto* enumeration_type = builder.createEnumerationType(scope, name, file, line, bit_size, alignment, enumerators, underlying_type);
|
||||
return enumeration_type;
|
||||
}
|
||||
|
||||
extern "C" DICompositeType* NativityLLVMDebugInfoBuilderCreateReplaceableCompositeType(DIBuilder& builder, unsigned tag, const char* name_ptr, size_t name_len, DIScope* scope, DIFile* file, unsigned line)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* composite_type = builder.createReplaceableCompositeType(tag, name, scope, file, line);
|
||||
return composite_type;
|
||||
}
|
||||
extern "C" DISubprogram* NativityLLVMDebugInfoScopeToSubprogram(DIScope* scope)
|
||||
{
|
||||
auto* subprogram = dyn_cast<DISubprogram>(scope);
|
||||
return subprogram;
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMDebugInfoBuilderFinalizeSubprogram(DIBuilder& builder, DISubprogram* subprogram, const Function* function)
|
||||
{
|
||||
assert(subprogram->describes(function));
|
||||
builder.finalizeSubprogram(subprogram);
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMDebugInfoBuilderFinalize(DIBuilder& builder)
|
||||
{
|
||||
builder.finalize();
|
||||
}
|
||||
|
||||
extern "C" DIFile* NativityLLVMDebugInfoSubprogramGetFile(DISubprogram& subprogram)
|
||||
{
|
||||
auto* file = subprogram.getFile();
|
||||
return file;
|
||||
}
|
||||
|
||||
extern "C" DIType* NativityLLVMDebugInfoSubprogramGetArgumentType(DISubprogram& subprogram, size_t argument_index)
|
||||
{
|
||||
auto* argument_type = subprogram.getType()->getTypeArray()[argument_index];
|
||||
return argument_type;
|
||||
}
|
||||
|
||||
extern "C" unsigned NativityLLVMArgumentGetIndex(Argument& argument)
|
||||
{
|
||||
unsigned argument_index = argument.getArgNo();
|
||||
return argument_index;
|
||||
}
|
||||
|
||||
extern "C" FunctionType* NativityLLVMGetFunctionType(Type* return_type, Type** type_ptr, size_t type_count, bool var_args)
|
||||
{
|
||||
auto types = ArrayRef<Type*>(type_ptr, type_count);
|
||||
auto* function_type = FunctionType::get(return_type, types, var_args);
|
||||
return function_type;
|
||||
}
|
||||
|
||||
extern "C" IntegerType* NativityLLVMGetIntegerType(LLVMContext& context, unsigned bit_count)
|
||||
{
|
||||
auto integer_type = IntegerType::get(context, bit_count);
|
||||
return integer_type;
|
||||
}
|
||||
|
||||
extern "C" PointerType* NativityLLVMGetPointerType(LLVMContext& context, unsigned address_space)
|
||||
{
|
||||
auto pointer_type = PointerType::get(context, address_space);
|
||||
return pointer_type;
|
||||
}
|
||||
|
||||
extern "C" ArrayType* NativityLLVMGetArrayType(Type* element_type, uint64_t element_count)
|
||||
{
|
||||
auto* array_type = ArrayType::get(element_type, element_count);
|
||||
return array_type;
|
||||
}
|
||||
|
||||
extern "C" StructType* NativityLLVMCreateStructType(LLVMContext& context, Type** type_ptr, size_t type_count, const char* name_ptr, size_t name_len, bool is_packed)
|
||||
{
|
||||
auto types = ArrayRef<Type*>(type_ptr, type_count);
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
|
||||
auto* struct_type = StructType::create(context, types, name, is_packed);
|
||||
return struct_type;
|
||||
}
|
||||
extern "C" Function* NativityLLVMModuleGetFunction(Module& module, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* function = module.getFunction(name);
|
||||
return function;
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMFunctionAddAttributeKey(Function& function, Attribute::AttrKind attribute)
|
||||
{
|
||||
function.addFnAttr(attribute);
|
||||
}
|
||||
|
||||
extern "C" Function* NativityLLVModuleCreateFunction(Module* module, FunctionType* function_type, GlobalValue::LinkageTypes linkage_type, unsigned address_space, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* function = Function::Create(function_type, linkage_type, address_space, name, module);
|
||||
return function;
|
||||
}
|
||||
|
||||
extern "C" BasicBlock* NativityLLVMCreateBasicBlock(LLVMContext& context, const char* name_ptr, size_t name_len, Function* parent, BasicBlock* insert_before)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* basic_block = BasicBlock::Create(context, name, parent, insert_before);
|
||||
return basic_block;
|
||||
}
|
||||
|
||||
extern "C" PHINode* NativityLLVMCreatePhiNode(Type* type, unsigned reserved_value_count, const char* name_ptr, size_t name_len, BasicBlock* basic_block)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* phi_node = PHINode::Create(type, reserved_value_count, name, basic_block);
|
||||
return phi_node;
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMBasicBlockRemoveFromParent(BasicBlock* basic_block)
|
||||
{
|
||||
basic_block->eraseFromParent();
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMBuilderSetInsertPoint(IRBuilder<>& builder, BasicBlock* basic_block)
|
||||
{
|
||||
builder.SetInsertPoint(basic_block);
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMValueSetName(Value* value, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
value->setName(name);
|
||||
}
|
||||
|
||||
extern "C" Type* NativityLLVMValueGetType(Value* value)
|
||||
{
|
||||
auto* type = value->getType();
|
||||
return type;
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMFunctionGetArguments(Function& function, Argument** argument_ptr, size_t* argument_count)
|
||||
{
|
||||
auto actual_argument_count = function.arg_size();
|
||||
assert(actual_argument_count <= *argument_count);
|
||||
*argument_count = actual_argument_count;
|
||||
size_t arg_i = 0;
|
||||
for (auto& Arg : function.args()) {
|
||||
argument_ptr[arg_i] = &Arg;
|
||||
arg_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMFunctionSetSubprogram(Function& function, DISubprogram* subprogram)
|
||||
{
|
||||
function.setSubprogram(subprogram);
|
||||
}
|
||||
|
||||
extern "C" DISubprogram* NativityLLVMFunctionGetSubprogram(Function& function)
|
||||
{
|
||||
auto* subprogram = function.getSubprogram();
|
||||
return subprogram;
|
||||
}
|
||||
|
||||
extern "C" Constant* NativityLLVMConstantStruct(StructType* struct_type, Constant** constant_ptr, size_t constant_count)
|
||||
{
|
||||
auto constants = ArrayRef<Constant*>(constant_ptr, constant_count);
|
||||
auto* constant_struct = ConstantStruct::get(struct_type, constants);
|
||||
return constant_struct;
|
||||
}
|
||||
|
||||
extern "C" StoreInst* NativityLLVMBuilderCreateStore(IRBuilder<>& builder, Value* value, Value* pointer, bool is_volatile)
|
||||
{
|
||||
auto* store = builder.CreateStore(value, pointer, is_volatile);
|
||||
return store;
|
||||
}
|
||||
|
||||
extern "C" AllocaInst* NativityLLVMBuilderCreateAlloca(IRBuilder<>& builder, Type* type, unsigned address_space, Value* array_size, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* alloca = builder.CreateAlloca(type, address_space, array_size, name);
|
||||
return alloca;
|
||||
}
|
||||
|
||||
extern "C" Type* NativityLLVMGetVoidType(LLVMContext& context)
|
||||
{
|
||||
auto* void_type = Type::getVoidTy(context);
|
||||
return void_type;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateICmp(IRBuilder<>& builder, CmpInst::Predicate comparation, Value* left, Value* right, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* icmp = builder.CreateICmp(comparation, left, right, name);
|
||||
return icmp;
|
||||
}
|
||||
|
||||
extern "C" LoadInst* NativityLLVMBuilderCreateLoad(IRBuilder<>& builder, Type* type, Value* value, bool is_volatile, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* load = builder.CreateLoad(type, value, is_volatile, name);
|
||||
return load;
|
||||
}
|
||||
|
||||
extern "C" ReturnInst* NativityLLVMBuilderCreateRet(IRBuilder<>& builder, Value* value)
|
||||
{
|
||||
auto* ret = builder.CreateRet(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" InlineAsm* NativityLLVMGetInlineAssembly(FunctionType* function_type, const char* assembly_ptr, size_t assembly_len, const char* constraints_ptr, size_t constrains_len, bool has_side_effects, bool is_align_stack, InlineAsm::AsmDialect dialect, bool can_throw)
|
||||
{
|
||||
auto assembly = StringRef(assembly_ptr, assembly_len);
|
||||
auto constraints = StringRef(constraints_ptr, constrains_len);
|
||||
auto* inline_asm = InlineAsm::get(function_type, assembly, constraints, has_side_effects, is_align_stack, dialect, can_throw);
|
||||
return inline_asm;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateCast(IRBuilder<>& builder, Instruction::CastOps cast_type, Value* value, Type* type, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* cast = builder.CreateCast(cast_type, value, type, name);
|
||||
return cast;
|
||||
}
|
||||
|
||||
extern "C" CallInst* NativityLLVMBuilderCreateCall(IRBuilder<>& builder, FunctionType* function_type, Value* callee, Value** argument_ptr, size_t argument_count, const char* name_ptr, size_t name_len, MDNode* fp_math_tag)
|
||||
{
|
||||
if (auto* foo = static_cast<FunctionType*>(callee->getType())) {
|
||||
int k = 0;
|
||||
}
|
||||
auto arguments = ArrayRef<Value*>(argument_ptr, argument_count);
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* call = builder.CreateCall(function_type, callee, arguments, name, fp_math_tag);
|
||||
return call;
|
||||
}
|
||||
|
||||
extern "C" UnreachableInst* NativityLLVMBuilderCreateUnreachable(IRBuilder<>& builder)
|
||||
{
|
||||
auto* unreachable = builder.CreateUnreachable();
|
||||
return unreachable;
|
||||
}
|
||||
|
||||
extern "C" GlobalVariable* NativityLLVMModuleAddGlobalVariable(Module& module, Type* type, bool is_constant, GlobalValue::LinkageTypes linkage_type, Constant* initializer, const char* name_ptr, size_t name_len, GlobalVariable* insert_before, GlobalValue::ThreadLocalMode thread_local_mode, unsigned address_space, bool externally_initialized)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* global_variable = new GlobalVariable(module, type, is_constant, linkage_type, initializer, name, insert_before, thread_local_mode, address_space, externally_initialized);
|
||||
return global_variable;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateAdd(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool no_unsigned_wrapping, bool no_signed_wrapping)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* add = builder.CreateAdd(left, right, name, no_unsigned_wrapping, no_signed_wrapping);
|
||||
return add;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateSub(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool no_unsigned_wrapping, bool no_signed_wrapping)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* add = builder.CreateSub(left, right, name, no_unsigned_wrapping, no_signed_wrapping);
|
||||
return add;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateMultiply(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool no_unsigned_wrapping, bool no_signed_wrapping)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* multiply = builder.CreateMul(left, right, name, no_unsigned_wrapping, no_signed_wrapping);
|
||||
return multiply;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateUDiv(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool is_exact)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateUDiv(left, right, name, is_exact);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateSDiv(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool is_exact)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateSDiv(left, right, name, is_exact);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateURem(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateURem(left, right, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateSRem(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateSRem(left, right, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateXor(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateXor(left, right, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateAnd(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateAnd(left, right, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateOr(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateOr(left, right, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateShiftLeft(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool no_unsigned_wrapping, bool no_signed_wrapping)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* shl = builder.CreateShl(left, right, name, no_unsigned_wrapping, no_signed_wrapping);
|
||||
return shl;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateLogicalShiftRight(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool is_exact)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateLShr(left, right, name, is_exact);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateArithmeticShiftRight(IRBuilder<>& builder, Value* left, Value* right, const char* name_ptr, size_t name_len, bool is_exact)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateAShr(left, right, name, is_exact);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateGEP(IRBuilder<>& builder, Type* type, Value* pointer, Value** index_ptr, size_t index_count, const char* name_ptr, size_t name_len, bool in_bounds)
|
||||
{
|
||||
auto index_list = ArrayRef<Value*>(index_ptr, index_count);
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* GEP = builder.CreateGEP(type, pointer, index_list, name, in_bounds);
|
||||
return GEP;
|
||||
}
|
||||
|
||||
extern "C" BranchInst* NativityLLVMBuilderCreateBranch(IRBuilder<>& builder, BasicBlock* basic_block)
|
||||
{
|
||||
auto* conditional_branch = builder.CreateBr(basic_block);
|
||||
return conditional_branch;
|
||||
}
|
||||
|
||||
extern "C" BranchInst* NativityLLVMBuilderCreateConditionalBranch(IRBuilder<>& builder, Value* condition, BasicBlock* true_block, BasicBlock* false_block, MDNode* branch_weights, MDNode* unpredictable)
|
||||
{
|
||||
auto* conditional_branch = builder.CreateCondBr(condition, true_block, false_block, branch_weights, unpredictable);
|
||||
return conditional_branch;
|
||||
}
|
||||
|
||||
extern "C" Intrinsic::ID NativityLLVMLookupIntrinsic(const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
Intrinsic::ID id = Function::lookupIntrinsicID(name);
|
||||
return id;
|
||||
}
|
||||
|
||||
extern "C" FunctionType* NativityLLVMContextGetIntrinsicType(LLVMContext& context, Intrinsic::ID intrinsic_id, Type** parameter_type_ptr, size_t parameter_type_count)
|
||||
{
|
||||
assert(intrinsic_id < Intrinsic::num_intrinsics);
|
||||
auto parameter_types = ArrayRef<Type*>(parameter_type_ptr, parameter_type_count);
|
||||
auto* function_type = Intrinsic::getType(context, intrinsic_id, parameter_types);
|
||||
return function_type;
|
||||
}
|
||||
|
||||
extern "C" Function* NativityLLVMModuleGetIntrinsicDeclaration(Module* module, Intrinsic::ID intrinsic_id, Type** parameter_types_ptr, size_t parameter_type_count)
|
||||
{
|
||||
auto parameter_types = ArrayRef<Type*>(parameter_types_ptr, parameter_type_count);
|
||||
assert(intrinsic_id < Intrinsic::num_intrinsics);
|
||||
Function* function = Intrinsic::getDeclaration(module, intrinsic_id, parameter_types);
|
||||
return function;
|
||||
}
|
||||
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateExtractValue(IRBuilder<>& builder, Value* aggregate, unsigned* indices_ptr, size_t indices_len, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto indices = ArrayRef<unsigned>(indices_ptr, indices_len);
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* value = builder.CreateExtractValue(aggregate, indices, name);
|
||||
return value;
|
||||
}
|
||||
|
||||
extern "C" Value* NativityLLVMBuilderCreateInsertValue(IRBuilder<>& builder, Value* aggregate, Value* value, unsigned* indices_ptr, size_t indices_len, const char* name_ptr, size_t name_len)
|
||||
{
|
||||
auto indices = ArrayRef<unsigned>(indices_ptr, indices_len);
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
auto* result = builder.CreateInsertValue(aggregate, value, indices, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" ConstantInt* NativityLLVMContextGetConstantInt(LLVMContext& context, unsigned bit_count, uint64_t value, bool is_signed)
|
||||
{
|
||||
auto int_type = APInt(bit_count, value, is_signed);
|
||||
auto constant_int = ConstantInt::get(context, int_type);
|
||||
return constant_int;
|
||||
}
|
||||
|
||||
extern "C" Constant* NativityLLVMContextGetConstString(LLVMContext& context, const char* string_ptr, size_t string_len, bool null_terminate)
|
||||
{
|
||||
auto string = StringRef(string_ptr, string_len);
|
||||
auto* constant = ConstantDataArray::getString(context, string, null_terminate);
|
||||
return constant;
|
||||
}
|
||||
|
||||
extern "C" Constant* NativityLLVMContextGetConstArray(ArrayType* array_type, Constant** value_ptr, size_t value_count)
|
||||
{
|
||||
auto values = ArrayRef<Constant*>(value_ptr, value_count);
|
||||
auto* constant_array = ConstantArray::get(array_type, values);
|
||||
return constant_array;
|
||||
}
|
||||
|
||||
extern "C" Constant* NativityLLVMContextCreateGlobalStringPointer(IRBuilder<>& builder, const char* string_ptr, size_t string_len, const char* name_ptr, size_t name_len, unsigned address_space, Module* module)
|
||||
{
|
||||
auto string = StringRef(string_ptr, string_len);
|
||||
auto name = StringRef(name_ptr, name_len);
|
||||
Constant* constant = builder.CreateGlobalStringPtr(string, name, address_space, module);
|
||||
return constant;
|
||||
}
|
||||
|
||||
extern "C" bool NativityLLVMVerifyFunction(Function& function, const char** message_ptr, size_t* message_len)
|
||||
{
|
||||
std::string message_buffer;
|
||||
raw_string_ostream message_stream(message_buffer);
|
||||
|
||||
bool result = verifyFunction(function, &message_stream);
|
||||
message_stream.flush();
|
||||
auto size = message_stream.str().size();
|
||||
*message_ptr = strndup(message_stream.str().c_str(), size);
|
||||
*message_len = size;
|
||||
|
||||
// We invert the condition because LLVM conventions are just stupid
|
||||
return !result;
|
||||
}
|
||||
|
||||
extern "C" bool NativityLLVMVerifyModule(const Module& module, const char** message_ptr, size_t* message_len)
|
||||
{
|
||||
std::string message_buffer;
|
||||
raw_string_ostream message_stream(message_buffer);
|
||||
|
||||
bool result = verifyModule(module, &message_stream);
|
||||
message_stream.flush();
|
||||
auto size = message_stream.str().size();
|
||||
*message_ptr = strndup(message_stream.str().c_str(), size);
|
||||
*message_len = size;
|
||||
|
||||
// We invert the condition because LLVM conventions are just stupid
|
||||
return !result;
|
||||
}
|
||||
|
||||
extern "C" Type* NativityLLVMFunctionGetReturnType(const Function& function)
|
||||
{
|
||||
auto* return_type = function.getReturnType();
|
||||
return return_type;
|
||||
}
|
||||
|
||||
extern "C" const char* NativityLLVMFunctionToString(const Function& function, size_t* len)
|
||||
{
|
||||
std::string buf;
|
||||
raw_string_ostream os(buf);
|
||||
function.print(os);
|
||||
os.flush();
|
||||
*len = buf.size();
|
||||
auto* result = strdup(buf.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" Type* NativityLLVMAllocatGetAllocatedType(AllocaInst& alloca)
|
||||
{
|
||||
auto* type = alloca.getAllocatedType();
|
||||
return type;
|
||||
}
|
||||
|
||||
extern "C" AllocaInst* NativityLLVMValueToAlloca(Value* value)
|
||||
{
|
||||
assert(value);
|
||||
auto* alloca = dyn_cast<AllocaInst>(value);
|
||||
return alloca;
|
||||
}
|
||||
|
||||
extern "C" Constant* NativityLLVMValueToConstant(Value* value)
|
||||
{
|
||||
assert(value);
|
||||
auto* constant = dyn_cast<Constant>(value);
|
||||
return constant;
|
||||
}
|
||||
|
||||
extern "C" Function* NativityLLVMValueToFunction(Value* value)
|
||||
{
|
||||
assert(value);
|
||||
auto* function = dyn_cast<Function>(value);
|
||||
return function;
|
||||
}
|
||||
|
||||
extern "C" bool NativityLLVMTypeIsPointer(Type* type)
|
||||
{
|
||||
bool is_pointer = type->isPointerTy();
|
||||
return is_pointer;
|
||||
}
|
||||
|
||||
extern "C" bool NativityLLVMTypeIsInteger(Type* type)
|
||||
{
|
||||
bool is_integer = type->isIntegerTy();
|
||||
return is_integer;
|
||||
}
|
||||
|
||||
extern "C" StructType* NativityLLVMTypeToStruct(Type* type)
|
||||
{
|
||||
auto* struct_type = dyn_cast<StructType>(type);
|
||||
return struct_type;
|
||||
}
|
||||
|
||||
extern "C" FunctionType* NativityLLVMTypeToFunction(Type* type)
|
||||
{
|
||||
auto* function_type = dyn_cast<FunctionType>(type);
|
||||
return function_type;
|
||||
}
|
||||
|
||||
extern "C" ArrayType* NativityLLVMTypeToArray(Type* type)
|
||||
{
|
||||
auto* array_type = dyn_cast<ArrayType>(type);
|
||||
return array_type;
|
||||
}
|
||||
|
||||
extern "C" Type* NativityLLVMArrayTypeGetElementType(ArrayType* array_type)
|
||||
{
|
||||
auto* element_type = array_type->getElementType();
|
||||
return element_type;
|
||||
}
|
||||
|
||||
extern "C" const char* NativityLLVMModuleToString(const Module& module, size_t* len)
|
||||
{
|
||||
std::string buf;
|
||||
raw_string_ostream os(buf);
|
||||
module.print(os, nullptr);
|
||||
os.flush();
|
||||
*len = buf.size();
|
||||
auto* result = strdup(buf.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" BasicBlock* NativityLLVMBuilderGetInsertBlock(IRBuilder<>& builder)
|
||||
{
|
||||
return builder.GetInsertBlock();
|
||||
}
|
||||
|
||||
extern "C" bool NativityLLVMBuilderIsCurrentBlockTerminated(IRBuilder<>& builder)
|
||||
{
|
||||
return builder.GetInsertBlock()->getTerminator() != nullptr;
|
||||
}
|
||||
|
||||
extern "C" UndefValue* NativityLLVMGetUndefined(Type* type)
|
||||
{
|
||||
auto* undefined_value = UndefValue::get(type);
|
||||
return undefined_value;
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMFunctionSetCallingConvention(Function& function, CallingConv::ID calling_convention)
|
||||
{
|
||||
function.setCallingConv(calling_convention);
|
||||
}
|
||||
|
||||
extern "C" CallingConv::ID NativityLLVMFunctionGetCallingConvention(Function& function)
|
||||
{
|
||||
auto calling_convention = function.getCallingConv();
|
||||
return calling_convention;
|
||||
}
|
||||
|
||||
extern "C" void NativityLLVMCallSetCallingConvention(CallBase& call_instruction, CallingConv::ID calling_convention)
|
||||
{
|
||||
call_instruction.setCallingConv(calling_convention);
|
||||
}
|
||||
|
||||
extern "C" Constant* NativityLLVMGetStruct(StructType* struct_type, Constant** constants_ptr, size_t constant_count)
|
||||
{
|
||||
auto constants = ArrayRef(constants_ptr, constant_count);
|
||||
auto* named_struct = ConstantStruct::get(struct_type, constants);
|
||||
return named_struct;
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
||||
llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
|
||||
}
|
||||
namespace elf {
|
||||
bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
||||
llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
|
||||
}
|
||||
namespace wasm {
|
||||
bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
||||
llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" bool NativityLLVMGenerateMachineCode(Module& module, const char* object_file_path_ptr, size_t object_file_path_len, const char* file_path_ptr, size_t file_path_len)
|
||||
{
|
||||
InitializeAllTargetInfos();
|
||||
InitializeAllTargets();
|
||||
InitializeAllTargetMCs(); InitializeAllAsmParsers();
|
||||
InitializeAllAsmPrinters();
|
||||
|
||||
auto target_triple = "x86_64-linux-none";
|
||||
auto cpu = "generic";
|
||||
auto features = "";
|
||||
TargetOptions target_options;
|
||||
|
||||
std::string error;
|
||||
auto* target = TargetRegistry::lookupTarget(target_triple, error);
|
||||
assert(target);
|
||||
|
||||
auto target_machine = target->createTargetMachine(target_triple, cpu, features, target_options, Reloc::Static);
|
||||
assert(target_machine);
|
||||
|
||||
module.setDataLayout(target_machine->createDataLayout());
|
||||
module.setTargetTriple(target_triple);
|
||||
|
||||
#if 0
|
||||
SmallVector<char> bytes;
|
||||
raw_svector_ostream message_stream(bytes);
|
||||
auto stream = buffer_ostream(message_stream);
|
||||
#else
|
||||
std::error_code EC;
|
||||
auto object_file_path = StringRef(object_file_path_ptr, object_file_path_len);
|
||||
raw_fd_ostream stream(object_file_path, EC, sys::fs::OF_None);
|
||||
if (EC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
legacy::PassManager pass;
|
||||
bool result = target_machine->addPassesToEmitFile(pass, stream, nullptr, llvm::CGFT_ObjectFile, false);
|
||||
if (result) {
|
||||
// We invert the condition because LLVM conventions are just stupid
|
||||
return false;
|
||||
}
|
||||
|
||||
pass.run(module);
|
||||
stream.flush();
|
||||
|
||||
std::vector<const char*> args;
|
||||
args.push_back("ld.lld");
|
||||
args.push_back(object_file_path_ptr);
|
||||
args.push_back("-o");
|
||||
args.push_back(file_path_ptr);
|
||||
|
||||
lld::elf::link(args, llvm::outs(), llvm::errs(), true, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool NativityLLVMCompareTypes(Type* a, Type* b)
|
||||
{
|
||||
if (auto* int_a = dyn_cast<IntegerType>(a)) {
|
||||
auto* int_b = dyn_cast<IntegerType>(b);
|
||||
assert(int_b);
|
||||
auto a_bit_count = int_a->getBitWidth();
|
||||
auto b_bit_count = int_b->getBitWidth();
|
||||
assert(a_bit_count == b_bit_count);
|
||||
}
|
||||
|
||||
return a == b;
|
||||
}
|
3489
bootstrap/backend/llvm.zig
Normal file
3489
bootstrap/backend/llvm.zig
Normal file
File diff suppressed because it is too large
Load Diff
118
bootstrap/backend/llvm_bindings.zig
Normal file
118
bootstrap/backend/llvm_bindings.zig
Normal file
@ -0,0 +1,118 @@
|
||||
const llvm = @import("llvm.zig");
|
||||
const LLVM = llvm.LLVM;
|
||||
pub extern fn NativityLLVMCreateContext() ?*LLVM.Context;
|
||||
pub extern fn NativityLLVMCreateModule(module_name_ptr: [*:0]const u8, module_name_len: usize, context: *LLVM.Context) ?*LLVM.Module;
|
||||
pub extern fn NativityLLVMCreateBuilder(context: *LLVM.Context) ?*LLVM.Builder;
|
||||
pub extern fn NativityLLVMGetFunctionType(return_type: *LLVM.Type, argument_type_ptr: [*]const *LLVM.Type, argument_type_len: usize, is_var_args: bool) ?*LLVM.Type.Function;
|
||||
pub extern fn NativityLLVMGetIntegerType(context: *LLVM.Context, bit_count: u32) ?*LLVM.Type.Integer;
|
||||
pub extern fn NativityLLVMGetPointerType(context: *LLVM.Context, address_space: u32) ?*LLVM.Type.Pointer;
|
||||
pub extern fn NativityLLVMGetArrayType(element_type: *LLVM.Type, element_count: u64) ?*LLVM.Type.Array;
|
||||
pub extern fn NativityLLVMCreateStructType(context: *LLVM.Context, type_ptr: [*]const *LLVM.Type, type_count: usize, name_ptr: [*]const u8, name_len: usize, is_packed: bool) ?*LLVM.Type.Struct;
|
||||
pub extern fn NativityLLVMConstantStruct(struct_type: *LLVM.Type.Struct, constant_ptr: [*]const *LLVM.Value.Constant, constant_count: usize) ?*LLVM.Value.Constant;
|
||||
pub extern fn NativityLLVMModuleGetFunction(module: *LLVM.Module, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value.Function;
|
||||
pub extern fn NativityLLVModuleCreateFunction(module: *LLVM.Module, function_type: *LLVM.Type.Function, linkage: LLVM.Linkage, address_space: c_uint, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value.Function;
|
||||
pub extern fn NativityLLVMModuleCreateDebugInfoBuilder(module: *LLVM.Module) ?*LLVM.DebugInfo.Builder;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateFile(builder: *LLVM.DebugInfo.Builder, filename_ptr: [*]const u8, filename_len: usize, directory_ptr: [*]const u8, directory_len: usize) ?*LLVM.DebugInfo.File;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateCompileUnit(builder: *LLVM.DebugInfo.Builder, language: LLVM.DebugInfo.Language, file: *LLVM.DebugInfo.File, producer_ptr: [*]const u8, producer_len: usize, is_optimized: bool, flags_ptr: [*]const u8, flags_len: usize, runtime_version: c_uint, split_name_ptr: [*]const u8, split_name_len: usize, debug_info_emission_kind: LLVM.DebugInfo.CompileUnit.EmissionKind, DWOId: u64, split_debug_inlining: bool, debug_info_for_profiling: bool, debug_info_name_table_kind: LLVM.DebugInfo.CompileUnit.NameTableKind, ranges_base_address: bool, sysroot_ptr: [*]const u8, sysroot_len: usize, sdk_ptr: [*]const u8, sdk_len: usize) ?*LLVM.DebugInfo.CompileUnit;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateFunction(builder: *LLVM.DebugInfo.Builder, scope: *LLVM.DebugInfo.Scope, name_ptr: [*]const u8, name_len: usize, linkage_name_ptr: [*]const u8, linkage_name_len: usize, file: *LLVM.DebugInfo.File, line_number: c_uint, type: *LLVM.DebugInfo.SubroutineType, scope_line: c_uint, flags: LLVM.DebugInfo.Node.Flags, subprogram_flags: LLVM.DebugInfo.Subprogram.Flags, declaration: ?*LLVM.DebugInfo.Subprogram) ?*LLVM.DebugInfo.Subprogram;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateSubroutineType(builder: *LLVM.DebugInfo.Builder, parameter_types_ptr: [*]const *LLVM.DebugInfo.Type, parameter_type_count: usize, flags: LLVM.DebugInfo.Node.Flags, calling_convention: LLVM.DebugInfo.CallingConvention) ?*LLVM.DebugInfo.SubroutineType;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateLexicalBlock(builder: *LLVM.DebugInfo.Builder, parent_scope: *LLVM.DebugInfo.Scope, parent_file: *LLVM.DebugInfo.File, line: c_uint, column: c_uint) ?*LLVM.DebugInfo.LexicalBlock;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateParameterVariable(builder: *LLVM.DebugInfo.Builder, scope: *LLVM.DebugInfo.Scope, name_ptr: [*]const u8, name_len: usize, argument_index: c_uint, file: *LLVM.DebugInfo.File, line_number: c_uint, type: *LLVM.DebugInfo.Type, always_preserve: bool, flags: LLVM.DebugInfo.Node.Flags) ?*LLVM.DebugInfo.LocalVariable;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateAutoVariable(builder: *LLVM.DebugInfo.Builder, scope: *LLVM.DebugInfo.Scope, name_ptr: [*]const u8, name_len: usize, file: *LLVM.DebugInfo.File, line_number: c_uint, type: *LLVM.DebugInfo.Type, always_preserve: bool, flags: LLVM.DebugInfo.Node.Flags, alignment: u32) ?*LLVM.DebugInfo.LocalVariable; // 0 means 1 << 0 (alignment of 1)
|
||||
pub extern fn NativityLLVMDebugInfoBuilderInsertDeclare(builder: *LLVM.DebugInfo.Builder, pointer: *LLVM.Value, local_variable: *LLVM.DebugInfo.LocalVariable, context: *LLVM.Context, line: c_uint, column: c_uint, scope: *LLVM.DebugInfo.Scope, basic_block: *LLVM.Value.BasicBlock) ?*LLVM.Value.Instruction;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateBasicType(builder: *LLVM.DebugInfo.Builder, name_ptr: [*]const u8, name_len: usize, bit_count: u64, dwarf_encoding: LLVM.DebugInfo.AttributeType, flags: LLVM.DebugInfo.Node.Flags) ?*LLVM.DebugInfo.Type;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreatePointerType(builder: *LLVM.DebugInfo.Builder, element_type: *LLVM.DebugInfo.Type, pointer_bit_count: u64, alignment: u32, name_ptr: [*]const u8, name_len: usize) ?*LLVM.DebugInfo.Type.Derived;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateStructType(builder: *LLVM.DebugInfo.Builder, scope: ?*LLVM.DebugInfo.Scope, name_ptr: [*]const u8, name_len: usize, file: ?*LLVM.DebugInfo.File, line_number: c_uint, bit_count: u64, alignment: u32, flags: LLVM.DebugInfo.Node.Flags, derived_from: ?*LLVM.DebugInfo.Type, element_type_ptr: [*]const *LLVM.DebugInfo.Type, element_type_count: usize) ?*LLVM.DebugInfo.Type.Composite;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateArrayType(builder: *LLVM.DebugInfo.Builder, bit_size: u64, alignment: u32, type: *LLVM.DebugInfo.Type, element_count: usize) ?*LLVM.DebugInfo.Type.Composite;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateEnumerationType(builder: *LLVM.DebugInfo.Builder, scope: ?*LLVM.DebugInfo.Scope, name_ptr: [*]const u8, name_len: usize, file: *LLVM.DebugInfo.File, line: c_uint, bit_size: u64, alignment: u32, enumerator_ptr: [*]const *LLVM.DebugInfo.Type.Enumerator, enumerator_count: usize, underlying_type: *LLVM.DebugInfo.Type) ?*LLVM.DebugInfo.Type.Composite;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateEnumerator(builder: *LLVM.DebugInfo.Builder, name_ptr: [*]const u8, name_len: usize, value: u64, is_unsigned: bool) ?*LLVM.DebugInfo.Type.Enumerator;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderCreateReplaceableCompositeType(builder: *LLVM.DebugInfo.Builder, tag: c_uint, name_ptr: [*]const u8, name_len: usize, scope: ?*LLVM.DebugInfo.Scope, file: ?*LLVM.DebugInfo.File, line: c_uint) ?*LLVM.DebugInfo.Type.Composite;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderFinalizeSubprogram(builder: *LLVM.DebugInfo.Builder, subprogram: *LLVM.DebugInfo.Subprogram, function: *LLVM.Value.Function) void;
|
||||
pub extern fn NativityLLVMDebugInfoBuilderFinalize(builder: *LLVM.DebugInfo.Builder) void;
|
||||
pub extern fn NativityLLVMDebugInfoSubprogramGetFile(subprogram: *LLVM.DebugInfo.Subprogram) ?*LLVM.DebugInfo.File;
|
||||
pub extern fn NativityLLVMDebugInfoSubprogramGetArgumentType(subprogram: *LLVM.DebugInfo.Subprogram, argument_index: usize) ?*LLVM.DebugInfo.Type;
|
||||
pub extern fn NativityLLVMDebugInfoScopeToSubprogram(scope: *LLVM.DebugInfo.Scope) ?*LLVM.DebugInfo.Subprogram;
|
||||
pub extern fn NativityLLVMCreateBasicBlock(context: *LLVM.Context, name_ptr: [*]const u8, name_len: usize, parent_function: ?*LLVM.Value.Function, insert_before: ?*LLVM.Value.BasicBlock) ?*LLVM.Value.BasicBlock;
|
||||
pub extern fn NativityLLVMBasicBlockRemoveFromParent(basic_block: *LLVM.Value.BasicBlock) void;
|
||||
pub extern fn NativityLLVMBuilderSetInsertPoint(builder: *LLVM.Builder, basic_block: *LLVM.Value.BasicBlock) void;
|
||||
pub extern fn NativityLLVMBuilderGetInsertBlock(builder: *LLVM.Builder) ?*LLVM.Value.BasicBlock;
|
||||
pub extern fn NativityLLVMBuilderSetCurrentDebugLocation(builder: *LLVM.Builder, context: *LLVM.Context, line: c_uint, column: c_uint, scope: *LLVM.DebugInfo.Scope, function: *LLVM.Value.Function) void;
|
||||
pub extern fn NativityLLVMValueSetName(value: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) void;
|
||||
pub extern fn NativityLLVMValueGetType(value: *LLVM.Value) *LLVM.Type;
|
||||
pub extern fn NativityLLVMArgumentGetIndex(argument: *LLVM.Value.Argument) c_uint;
|
||||
pub extern fn NativityLLVMFunctionGetArguments(function: *LLVM.Value.Function, argument_ptr: [*]*LLVM.Value.Argument, argument_len: *usize) void;
|
||||
pub extern fn NativityLLVMFunctionGetReturnType(function: *LLVM.Value.Function) ?*LLVM.Type;
|
||||
pub extern fn NativityLLVMBuilderCreateAlloca(builder: *LLVM.Builder, type: *LLVM.Type, address_space: c_uint, array_size: ?*LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value.Instruction.Alloca;
|
||||
pub extern fn NativityLLVMBuilderCreateStore(builder: *LLVM.Builder, value: *LLVM.Value, pointer: *LLVM.Value, is_volatile: bool) ?*LLVM.Value.Instruction.Store;
|
||||
pub extern fn NativityLLVMContextGetConstantInt(context: *LLVM.Context, bit_count: c_uint, value: u64, is_signed: bool) ?*LLVM.Value.Constant.Int;
|
||||
pub extern fn NativityLLVMContextGetConstString(context: *LLVM.Context, name_ptr: [*]const u8, name_len: usize, null_terminate: bool) ?*LLVM.Value.Constant;
|
||||
pub extern fn NativityLLVMContextGetConstArray(array_type: *LLVM.Type.Array, value_ptr: [*]const *LLVM.Value.Constant, value_count: usize) ?*LLVM.Value.Constant;
|
||||
pub extern fn NativityLLVMBuilderCreateICmp(builder: *LLVM.Builder, integer_comparison: LLVM.Value.Instruction.ICmp.Kind, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateLoad(builder: *LLVM.Builder, type: *LLVM.Type, value: *LLVM.Value, is_volatile: bool, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value.Instruction.Load;
|
||||
pub extern fn NativityLLVMBuilderCreateRet(builder: *LLVM.Builder, value: ?*LLVM.Value) ?*LLVM.Value.Instruction.Ret;
|
||||
pub extern fn NativityLLVMBuilderCreateCast(builder: *LLVM.Builder, cast_type: LLVM.Value.Instruction.Cast.Type, value: *LLVM.Value, type: *LLVM.Type, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMFunctionAddAttributeKey(builder: *LLVM.Value.Function, attribute_key: LLVM.Attribute) void;
|
||||
pub extern fn NativityLLVMGetVoidType(context: *LLVM.Context) ?*LLVM.Type;
|
||||
pub extern fn NativityLLVMGetInlineAssembly(function_type: *LLVM.Type.Function, assembly_ptr: [*]const u8, assembly_len: usize, constraints_ptr: [*]const u8, constrains_len: usize, has_side_effects: bool, is_align_stack: bool, dialect: LLVM.Value.InlineAssembly.Dialect, can_throw: bool) ?*LLVM.Value.InlineAssembly;
|
||||
pub extern fn NativityLLVMBuilderCreateCall(builder: *LLVM.Builder, function_type: *LLVM.Type.Function, callee: *LLVM.Value, argument_ptr: [*]const *LLVM.Value, argument_count: usize, name_ptr: [*]const u8, name_len: usize, fp_math_tag: ?*LLVM.Metadata.Node) ?*LLVM.Value.Instruction.Call;
|
||||
pub extern fn NativityLLVMBuilderCreateUnreachable(builder: *LLVM.Builder) ?*LLVM.Value.Instruction.Unreachable;
|
||||
pub extern fn NativityLLVMModuleAddGlobalVariable(module: *LLVM.Module, type: *LLVM.Type, is_constant: bool, linkage: LLVM.Linkage, initializer: ?*LLVM.Value.Constant, name_ptr: [*]const u8, name_len: usize, insert_before: ?*LLVM.Value.Constant.GlobalVariable, thread_local_mode: LLVM.ThreadLocalMode, address_space: c_uint, externally_initialized: bool) ?*LLVM.Value.Constant.GlobalVariable;
|
||||
|
||||
pub extern fn NativityLLVMBuilderCreateAdd(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, no_unsigned_wrapping: bool, no_signed_wrapping: bool) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateSub(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, no_unsigned_wrapping: bool, no_signed_wrapping: bool) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateMultiply(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, no_unsigned_wrapping: bool, no_signed_wrapping: bool) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateShiftLeft(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, no_unsigned_wrapping: bool, no_signed_wrapping: bool) ?*LLVM.Value;
|
||||
|
||||
pub extern fn NativityLLVMBuilderCreateUDiv(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, is_exact: bool) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateSDiv(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, is_exact: bool) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateURem(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateSRem(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateLogicalShiftRight(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, is_exact: bool) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateArithmeticShiftRight(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize, is_exact: bool) ?*LLVM.Value;
|
||||
|
||||
pub extern fn NativityLLVMBuilderCreateXor(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateAnd(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateOr(builder: *LLVM.Builder, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateGEP(builder: *LLVM.Builder, type: *LLVM.Type, pointer: *LLVM.Value, index_ptr: [*]const *LLVM.Value, index_count: usize, name_ptr: [*]const u8, name_len: usize, in_bounds: bool) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateBranch(builder: *LLVM.Builder, basic_block: *LLVM.Value.BasicBlock) ?*LLVM.Value.Instruction.Branch;
|
||||
pub extern fn NativityLLVMBuilderCreateConditionalBranch(builder: *LLVM.Builder, condition: *LLVM.Value, true_block: *LLVM.Value.BasicBlock, false_block: *LLVM.Value.BasicBlock, branch_weights: ?*LLVM.Metadata.Node, unpredictable: ?*LLVM.Metadata.Node) ?*LLVM.Value.Instruction.Branch;
|
||||
|
||||
pub extern fn NativityLLVMVerifyFunction(function: *LLVM.Value.Function, message_ptr: *[*]const u8, message_len: *usize) bool;
|
||||
pub extern fn NativityLLVMVerifyModule(module: *LLVM.Module, message_ptr: *[*]const u8, message_len: *usize) bool;
|
||||
|
||||
pub extern fn NativityLLVMModuleToString(module: *LLVM.Module, message_len: *usize) [*]const u8;
|
||||
pub extern fn NativityLLVMFunctionToString(function: *LLVM.Value.Function, message_len: *usize) [*]const u8;
|
||||
|
||||
pub extern fn NativityLLVMGenerateMachineCode(module: *LLVM.Module, object_file_path_ptr: [*]const u8, object_file_path_len: usize, file_path_ptr: [*]const u8, file_path_len: usize) bool;
|
||||
pub extern fn NativityLLVMBuilderIsCurrentBlockTerminated(builder: *LLVM.Builder) bool;
|
||||
pub extern fn NativityLLVMGetUndefined(type: *LLVM.Type) ?*LLVM.Value.Constant.Undefined;
|
||||
pub extern fn NativityLLVMFunctionSetCallingConvention(function: *LLVM.Value.Function, calling_convention: LLVM.Value.Function.CallingConvention) void;
|
||||
pub extern fn NativityLLVMFunctionGetCallingConvention(function: *LLVM.Value.Function) LLVM.Value.Function.CallingConvention;
|
||||
pub extern fn NativityLLVMFunctionSetSubprogram(function: *LLVM.Value.Function, subprogram: *LLVM.DebugInfo.Subprogram) void;
|
||||
pub extern fn NativityLLVMFunctionGetSubprogram(function: *LLVM.Value.Function) ?*LLVM.DebugInfo.Subprogram;
|
||||
|
||||
pub extern fn NativityLLVMCallSetCallingConvention(instruction: *LLVM.Value.Instruction.Call, calling_convention: LLVM.Value.Function.CallingConvention) void;
|
||||
pub extern fn NativityLLVMGetStruct(struct_type: *LLVM.Type.Struct, constant_ptr: [*]const *LLVM.Value.Constant, constant_len: usize) ?*LLVM.Value.Constant;
|
||||
|
||||
pub extern fn NativityLLVMValueToConstant(value: *LLVM.Value) ?*LLVM.Value.Constant;
|
||||
pub extern fn NativityLLVMValueToFunction(value: *LLVM.Value) ?*LLVM.Value.Function;
|
||||
|
||||
pub extern fn NativityLLVMTypeIsPointer(type: *LLVM.Type) bool;
|
||||
pub extern fn NativityLLVMTypeIsInteger(type: *LLVM.Type) bool;
|
||||
|
||||
pub extern fn NativityLLVMTypeToStruct(type: *LLVM.Type) ?*LLVM.Type.Struct;
|
||||
pub extern fn NativityLLVMTypeToFunction(type: *LLVM.Type) ?*LLVM.Type.Function;
|
||||
pub extern fn NativityLLVMTypeToArray(type: *LLVM.Type) ?*LLVM.Type.Array;
|
||||
|
||||
pub extern fn NativityLLVMArrayTypeGetElementType(array_type: *LLVM.Type.Array) ?*LLVM.Type;
|
||||
pub extern fn NativityLLVMLookupIntrinsic(name_ptr: [*]const u8, name_len: usize) LLVM.Value.IntrinsicID;
|
||||
pub extern fn NativityLLVMModuleGetIntrinsicDeclaration(module: *LLVM.Module, intrinsic_id: LLVM.Value.IntrinsicID, parameter_types_ptr: [*]const *LLVM.Type, parameter_type_count: usize) ?*LLVM.Value.Function;
|
||||
pub extern fn NativityLLVMContextGetIntrinsicType(context: *LLVM.Context, intrinsic_id: LLVM.Value.IntrinsicID, parameter_type_ptr: [*]const *LLVM.Type, parameter_type_count: usize) ?*LLVM.Type.Function;
|
||||
pub extern fn NativityLLVMBuilderCreateExtractValue(builder: *LLVM.Builder, aggregate: *LLVM.Value, indices_ptr: [*]const c_uint, indices_len: usize, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMBuilderCreateInsertValue(builder: *LLVM.Builder, aggregate: *LLVM.Value, value: *LLVM.Value, indices_ptr: [*]const c_uint, indices_len: usize, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||
pub extern fn NativityLLVMContextCreateGlobalStringPointer(builder: *LLVM.Builder, string_ptr: [*]const u8, string_len: usize, name_ptr: [*]const u8, name_len: usize, address_space: c_uint, module: *LLVM.Module) ?*LLVM.Value.Constant;
|
||||
pub extern fn NativityLLVMCompareTypes(a: *LLVM.Type, b: *LLVM.Type) bool;
|
||||
pub extern fn NativityLLVMCreatePhiNode(type: *LLVM.Type, reserved_value_count: c_uint, name_ptr: [*]const u8, name_len: usize, basic_block: ?*LLVM.Value.BasicBlock) ?*LLVM.Value.Instruction.PhiNode;
|
||||
|
||||
pub extern fn NativityLLVMAllocatGetAllocatedType(alloca: *LLVM.Value.Instruction.Alloca) *LLVM.Type;
|
||||
pub extern fn NativityLLVMValueToAlloca(value: *LLVM.Value) ?*LLVM.Value.Instruction.Alloca;
|
@ -6,204 +6,163 @@ pub const AutoArrayHashMap = std.AutoArrayHashMapUnmanaged;
|
||||
pub const ArrayList = std.ArrayListUnmanaged;
|
||||
pub const ArrayListAligned = std.ArrayListAlignedUnmanaged;
|
||||
pub const AutoHashMap = std.AutoHashMapUnmanaged;
|
||||
pub const BoundedArray = std.BoundedArray;
|
||||
pub const HashMap = std.HashMapUnmanaged;
|
||||
pub const SegmentedList = std.SegmentedList;
|
||||
pub const StringHashMap = std.StringHashMapUnmanaged;
|
||||
pub const StringArrayHashMap = std.StringArrayHashMapUnmanaged;
|
||||
|
||||
pub fn BlockList(comptime T: type) type {
|
||||
pub fn BlockList(comptime T: type, comptime E: type) type {
|
||||
const item_count = 64;
|
||||
const Block = struct {
|
||||
items: [item_count]T = undefined,
|
||||
bitset: Bitset = Bitset.initEmpty(),
|
||||
|
||||
const Bitset = std.StaticBitSet(item_count);
|
||||
|
||||
fn allocateIndex(block: *@This()) !u6 {
|
||||
if (block.bitset.mask != std.math.maxInt(@TypeOf(block.bitset.mask))) {
|
||||
const index = @ctz(~block.bitset.mask);
|
||||
block.bitset.set(index);
|
||||
return @intCast(index);
|
||||
} else {
|
||||
return error.OutOfMemory;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return struct {
|
||||
// TODO: make this not reallocate the whole block. Instead, use a pointer to the block as the ArrayList item
|
||||
blocks: ArrayList(*Block) = .{},
|
||||
len: usize = 0,
|
||||
first_block: u32 = 0,
|
||||
|
||||
const Block = BoundedArray(T, item_count);
|
||||
const List = @This();
|
||||
|
||||
pub const Index = packed struct(u32) {
|
||||
element: u6,
|
||||
block: u24,
|
||||
_reserved: bool = false,
|
||||
invalid: bool = false,
|
||||
pub const Index = getIndexForType(T, E);
|
||||
pub const ElementIndex = Index.Index;
|
||||
|
||||
pub const invalid = Index{
|
||||
.invalid = true,
|
||||
.element = 0,
|
||||
.block = 0,
|
||||
};
|
||||
// pub const append = switch (list_type) {
|
||||
// .index => appendIndexed,
|
||||
// .pointer => appendPointer,
|
||||
// };
|
||||
// pub const addOne = switch (list_type) {
|
||||
// .index => addOneIndexed,
|
||||
// .pointer => addOnePointer,
|
||||
// };
|
||||
|
||||
pub fn eq(index: Index, other: Index) bool {
|
||||
return @as(u32, @bitCast(index)) == @as(u32, @bitCast(other));
|
||||
pub fn wrapSplit(block: usize, element: usize) ElementIndex {
|
||||
return @enumFromInt(block * item_count + element);
|
||||
}
|
||||
|
||||
pub fn uniqueInteger(index: Index) u32 {
|
||||
assert(!index.invalid);
|
||||
return @as(u30, @truncate(@as(u32, @bitCast(index))));
|
||||
pub fn get(list: *List, index: ElementIndex) *T {
|
||||
assert(index != .null);
|
||||
const i: u32 = @intFromEnum(index);
|
||||
const block_index = i / item_count;
|
||||
const element_index = i % item_count;
|
||||
const block = list.blocks.items[block_index];
|
||||
const block_slice = block.buffer[0..block.len];
|
||||
const element = &block_slice[element_index];
|
||||
return element;
|
||||
}
|
||||
|
||||
pub fn fromInteger(usize_index: usize) Index {
|
||||
const index: u32 = @intCast(usize_index);
|
||||
const block: u24 = @intCast(index / item_count);
|
||||
const i: u6 = @intCast(index % item_count);
|
||||
return .{
|
||||
.element = i,
|
||||
.block = block,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Iterator = struct {
|
||||
index: Index,
|
||||
list: *List,
|
||||
|
||||
pub const Pair = struct {
|
||||
index: Index,
|
||||
};
|
||||
|
||||
pub fn nextIndex(i: *Iterator) ?Index {
|
||||
// TODO: optimize with ctz and masking out already iterated indices in the bitmask
|
||||
for (i.index.block..i.list.blocks.items.len) |block_index| {
|
||||
for (@as(u8, i.index.element)..item_count) |element_index| {
|
||||
if (i.list.blocks.items[block_index].bitset.isSet(element_index)) {
|
||||
const index = Index{
|
||||
.element = @intCast(element_index),
|
||||
.block = @intCast(block_index),
|
||||
};
|
||||
|
||||
i.index = index;
|
||||
i.index.element +%= 1;
|
||||
i.index.block = @as(u24, @intCast(block_index)) + @intFromBool(i.index.element < element_index);
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn nextPointer(i: *Iterator) ?*T {
|
||||
if (i.nextIndex()) |index| {
|
||||
const result = i.list.get(index);
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn iterator(list: *List) Iterator {
|
||||
return .{
|
||||
.index = Index{
|
||||
.element = 0,
|
||||
.block = 0,
|
||||
},
|
||||
.list = list,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(list: *List, index: Index) *T {
|
||||
assert(!index.invalid);
|
||||
return &list.blocks.items[index.block].items[index.element];
|
||||
}
|
||||
|
||||
pub fn append(list: *List, allocator: Allocator, element: T) !Index {
|
||||
pub fn append(list: *List, allocator: Allocator, element: T) !ElementIndex {
|
||||
const result = try list.addOne(allocator);
|
||||
list.get(result).* = element;
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addOne(list: *List, allocator: Allocator) !Index {
|
||||
try list.ensureCapacity(allocator, list.len + 1);
|
||||
const max_allocation = list.blocks.items.len * item_count;
|
||||
const result = switch (list.len < max_allocation) {
|
||||
true => blk: {
|
||||
const block = list.blocks.items[list.first_block];
|
||||
if (block.allocateIndex()) |element_index| {
|
||||
break :blk Index{
|
||||
.element = element_index,
|
||||
.block = @intCast(list.first_block),
|
||||
};
|
||||
} else |_| {
|
||||
@panic("TODO");
|
||||
pub fn addOne(list: *List, allocator: Allocator) !ElementIndex {
|
||||
const block_index = try list.getFreeBlock(allocator);
|
||||
const block = list.blocks.items[block_index];
|
||||
const index = block.len;
|
||||
_ = try block.addOne();
|
||||
return @enumFromInt(block_index * item_count + index);
|
||||
}
|
||||
},
|
||||
false => blk: {
|
||||
const block_index = list.blocks.items.len;
|
||||
|
||||
fn getFreeBlock(list: *List, allocator: Allocator) !usize {
|
||||
for (list.blocks.items, 0..) |block, i| {
|
||||
block.ensureUnusedCapacity(1) catch continue;
|
||||
return i;
|
||||
} else {
|
||||
const new_block = try allocator.create(Block);
|
||||
new_block.* = .{};
|
||||
list.blocks.appendAssumeCapacity(new_block);
|
||||
const element_index = new_block.allocateIndex() catch unreachable;
|
||||
list.first_block += @intFromBool(block_index != 0);
|
||||
break :blk Index{
|
||||
.element = element_index,
|
||||
.block = @intCast(block_index),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
list.len += 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn ensureCapacity(list: *List, allocator: Allocator, new_capacity: usize) !void {
|
||||
const max_allocation = list.blocks.items.len * item_count;
|
||||
if (max_allocation < new_capacity) {
|
||||
const block_count = new_capacity / item_count + @intFromBool(new_capacity % item_count != 0);
|
||||
try list.blocks.ensureTotalCapacity(allocator, block_count);
|
||||
const block_index = list.blocks.items.len;
|
||||
try list.blocks.append(allocator, new_block);
|
||||
return block_index;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indexOf(list: *List, elem: *const T) Index {
|
||||
pub fn indexOf(list: *List, elem: *const T) ElementIndex {
|
||||
const address = @intFromPtr(elem);
|
||||
for (list.blocks.items, 0..) |*block, block_index| {
|
||||
const base = @intFromPtr(&block.items[0]);
|
||||
for (list.blocks.items, 0..) |block, block_index| {
|
||||
const base = @intFromPtr(&block.buffer[0]);
|
||||
const top = base + @sizeOf(T) * item_count;
|
||||
if (address >= base and address < top) {
|
||||
return .{
|
||||
.block = @intCast(block_index),
|
||||
.element = @intCast(@divExact(address - base, @sizeOf(T))),
|
||||
};
|
||||
const result: u32 = @intCast(block_index * item_count + @divExact(address - base, @sizeOf(T)));
|
||||
return Index.wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
@panic("not found");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "Bitset index allocation" {
|
||||
const expect = std.testing.expect;
|
||||
var block = Block{};
|
||||
for (0..item_count) |expected_index| {
|
||||
const new_index = try block.allocateIndex();
|
||||
try expect(new_index == expected_index);
|
||||
pub fn getIndexForType(comptime T: type, comptime E: type) type {
|
||||
assert(@typeInfo(E) == .Enum);
|
||||
_ = T;
|
||||
const IndexType = u32;
|
||||
const MAX = std.math.maxInt(IndexType);
|
||||
|
||||
const EnumField = std.builtin.Type.EnumField;
|
||||
comptime var fields: []const EnumField = &.{};
|
||||
// comptime var enum_value: comptime_int = 0;
|
||||
fields = fields ++ @typeInfo(E).Enum.fields;
|
||||
|
||||
// for (names) |name| {
|
||||
// fields = fields ++ [1]EnumField{.{
|
||||
// .name = name,
|
||||
// .value = enum_value,
|
||||
// }};
|
||||
// enum_value += 1;
|
||||
// }
|
||||
|
||||
fields = fields ++ [1]EnumField{.{
|
||||
.name = "null",
|
||||
.value = MAX,
|
||||
}};
|
||||
|
||||
const Result = @Type(.{
|
||||
.Enum = .{
|
||||
.tag_type = IndexType,
|
||||
.fields = fields,
|
||||
.decls = &.{},
|
||||
.is_exhaustive = false,
|
||||
},
|
||||
});
|
||||
|
||||
return struct {
|
||||
pub const Index = Result;
|
||||
|
||||
pub fn unwrap(this: Index) IndexType {
|
||||
assert(this != .null);
|
||||
return @intFromEnum(this);
|
||||
}
|
||||
|
||||
_ = block.allocateIndex() catch return;
|
||||
pub fn wrap(value: IndexType) Index {
|
||||
assert(value < MAX);
|
||||
return @enumFromInt(value);
|
||||
}
|
||||
|
||||
return error.TestUnexpectedResult;
|
||||
pub fn addInt(this: Index, value: IndexType) Index{
|
||||
const this_int = @intFromEnum(this);
|
||||
return @enumFromInt(this_int + value);
|
||||
}
|
||||
|
||||
pub fn subInt(this: Index, value: IndexType) IndexType{
|
||||
const this_int = @intFromEnum(this);
|
||||
return this_int - value;
|
||||
}
|
||||
|
||||
pub fn add(a: Index, b: Index) Index{
|
||||
return @enumFromInt(@intFromEnum(a) + @intFromEnum(b));
|
||||
}
|
||||
|
||||
pub fn sub(a: Index, b: Index) IndexType{
|
||||
return @intFromEnum(a) - @intFromEnum(b);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub const ListType = enum{
|
||||
index,
|
||||
pointer,
|
||||
};
|
||||
|
||||
|
||||
pub fn enumFromString(comptime E: type, string: []const u8) ?E {
|
||||
return inline for (@typeInfo(E).Enum.fields) |enum_field| {
|
||||
if (std.mem.eql(u8, string, enum_field.name)) {
|
||||
|
435
bootstrap/frontend/lexer.zig
Normal file
435
bootstrap/frontend/lexer.zig
Normal file
@ -0,0 +1,435 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log;
|
||||
|
||||
const equal = std.mem.eql;
|
||||
|
||||
const data_structures = @import("../data_structures.zig");
|
||||
const ArrayList = data_structures.ArrayList;
|
||||
const enumFromString = data_structures.enumFromString;
|
||||
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const File = Compilation.File;
|
||||
const logln = Compilation.logln;
|
||||
const Token = Compilation.Token;
|
||||
const fs = @import("../fs.zig");
|
||||
|
||||
|
||||
// Needed information
|
||||
// Token: u8
|
||||
// line: u32
|
||||
// column: u16
|
||||
// offset: u32
|
||||
// len: u24
|
||||
|
||||
pub const Result = struct {
|
||||
offset: Token.Index,
|
||||
count: u32,
|
||||
line_offset: u32,
|
||||
line_count: u32,
|
||||
// ids: ArrayList(Token.Id) = .{},
|
||||
// token_lines: ArrayList(u32) = .{},
|
||||
// file_line_offsets: ArrayList(u32) = .{},
|
||||
// token_offsets: ArrayList(u32) = .{},
|
||||
// token_lengths: ArrayList(u32) = .{},
|
||||
time: u64 = 0,
|
||||
};
|
||||
|
||||
pub const Logger = enum {
|
||||
start,
|
||||
end,
|
||||
new_token,
|
||||
number_literals,
|
||||
|
||||
pub var bitset = std.EnumSet(Logger).initMany(&.{
|
||||
.new_token,
|
||||
.start,
|
||||
.end,
|
||||
.number_literals,
|
||||
});
|
||||
};
|
||||
|
||||
pub fn analyze(allocator: Allocator, text: []const u8, token_buffer: *Token.Buffer) !Result {
|
||||
assert(text.len <= std.math.maxInt(u32));
|
||||
const len: u32 = @intCast(text.len);
|
||||
|
||||
var lexer = Result{
|
||||
.offset = token_buffer.getOffset(),
|
||||
.line_offset = token_buffer.getLineOffset(),
|
||||
.count = 0,
|
||||
.line_count = 0,
|
||||
};
|
||||
|
||||
const time_start = std.time.Instant.now() catch unreachable;
|
||||
|
||||
try token_buffer.line_offsets.append(allocator, 0);
|
||||
|
||||
for (text, 0..) |byte, index| {
|
||||
if (byte == '\n') {
|
||||
try token_buffer.line_offsets.append(allocator, @intCast(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
var index: u32 = 0;
|
||||
var line_index: u32 = lexer.line_offset;
|
||||
|
||||
try token_buffer.tokens.ensureUnusedCapacity(allocator, text.len / 4);
|
||||
|
||||
logln(.lexer, .end, "START LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{Token.unwrap(lexer.offset), lexer.line_offset});
|
||||
|
||||
while (index < len) {
|
||||
const start_index = index;
|
||||
const start_character = text[index];
|
||||
|
||||
const token_id: Token.Id = switch (start_character) {
|
||||
'a'...'z', 'A'...'Z', '_' => blk: {
|
||||
while (true) {
|
||||
const ch = text[index];
|
||||
if ((ch >= 'a' and ch <= 'z') or (ch >= 'A' and ch <= 'Z') or ch == '_' or (ch >= '0' and ch <= '9')) {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// const identifier = text[start_index..][0 .. index - start_index];
|
||||
// logln("Identifier: {s}", .{identifier});
|
||||
|
||||
if (start_character == 'u' or start_character == 's' and text[start_index + 1] >= '0' and text[start_index + 1] <= '9') {
|
||||
var index_integer = start_index + 1;
|
||||
while (text[index_integer] >= '0' and text[index_integer] <= '9') {
|
||||
index_integer += 1;
|
||||
}
|
||||
|
||||
if (index_integer == index) {
|
||||
const id: Token.Id = switch (start_character) {
|
||||
'u' => .keyword_unsigned_integer,
|
||||
's' => .keyword_signed_integer,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
break :blk id;
|
||||
}
|
||||
}
|
||||
|
||||
const string = text[start_index..][0 .. index - start_index];
|
||||
break :blk if (enumFromString(Compilation.FixedKeyword, string)) |fixed_keyword| switch (fixed_keyword) {
|
||||
inline else => |comptime_fixed_keyword| @field(Token.Id, "fixed_keyword_" ++ @tagName(comptime_fixed_keyword)),
|
||||
} else if (equal(u8, string, "_")) .discard else .identifier;
|
||||
},
|
||||
'0'...'9' => blk: {
|
||||
// Detect other non-decimal literals
|
||||
if (text[index] == '0' and index + 1 < text.len) {
|
||||
if (text[index + 1] == 'x') {
|
||||
index += 2;
|
||||
} else if (text[index + 1] == 'b') {
|
||||
index += 2;
|
||||
} else if (text[index + 1] == 'o') {
|
||||
index += 2;
|
||||
}
|
||||
}
|
||||
|
||||
while (text[index] >= '0' and text[index] <= '9' or text[index] >= 'a' and text[index] <= 'f' or text[index] >= 'A' and text[index] <= 'F') {
|
||||
index += 1;
|
||||
}
|
||||
|
||||
break :blk .number_literal;
|
||||
},
|
||||
'\'' => blk: {
|
||||
index += 1;
|
||||
index += @intFromBool(text[index] == '\'');
|
||||
index += 1;
|
||||
const is_end_char_literal = text[index] == '\'';
|
||||
index += @intFromBool(is_end_char_literal);
|
||||
if (!is_end_char_literal) unreachable;
|
||||
|
||||
break :blk .character_literal;
|
||||
},
|
||||
'"' => blk: {
|
||||
index += 1;
|
||||
|
||||
while (true) {
|
||||
if (text[index] == '"' and text[index - 1] != '"') {
|
||||
break;
|
||||
}
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
index += 1;
|
||||
|
||||
break :blk .string_literal;
|
||||
},
|
||||
'#' => blk: {
|
||||
index += 1;
|
||||
// const start_intrinsic = index;
|
||||
|
||||
while (true) {
|
||||
const ch = text[index];
|
||||
if ((ch >= 'a' and ch <= 'z') or (ch >= 'A' and ch <= 'Z') or ch == '_') {
|
||||
index += 1;
|
||||
} else break;
|
||||
}
|
||||
|
||||
// const end_intrinsic = index;
|
||||
// const intrinsic_identifier = text[start_intrinsic..][0 .. end_intrinsic - start_intrinsic];
|
||||
// _ = intrinsic_identifier;
|
||||
|
||||
break :blk .intrinsic;
|
||||
},
|
||||
'\n' => {
|
||||
index += 1;
|
||||
line_index += 1;
|
||||
continue;
|
||||
},
|
||||
' ', '\r', '\t' => {
|
||||
index += 1;
|
||||
continue;
|
||||
},
|
||||
'(' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_left_parenthesis;
|
||||
},
|
||||
')' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_right_parenthesis;
|
||||
},
|
||||
'{' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_left_brace;
|
||||
},
|
||||
'}' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_right_brace;
|
||||
},
|
||||
'[' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_left_bracket;
|
||||
},
|
||||
']' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_right_bracket;
|
||||
},
|
||||
'<' => blk: {
|
||||
index += 1;
|
||||
switch (text[index]) {
|
||||
'<' => {
|
||||
index += 1;
|
||||
break :blk switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_shift_left_assign;
|
||||
},
|
||||
else => .operator_shift_left,
|
||||
};
|
||||
},
|
||||
'=' => {
|
||||
index += 1;
|
||||
break :blk .operator_compare_less_equal;
|
||||
},
|
||||
else =>break :blk .operator_compare_less,
|
||||
}
|
||||
},
|
||||
'>' => blk: {
|
||||
index += 1;
|
||||
switch (text[index]) {
|
||||
'>' => {
|
||||
index += 1;
|
||||
break :blk switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_shift_right_assign;
|
||||
},
|
||||
else => .operator_shift_right,
|
||||
};
|
||||
},
|
||||
'=' => {
|
||||
index += 1;
|
||||
break :blk .operator_compare_greater_equal;
|
||||
},
|
||||
else =>break :blk .operator_compare_greater,
|
||||
}
|
||||
},
|
||||
';' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_semicolon;
|
||||
},
|
||||
'@' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_at;
|
||||
},
|
||||
',' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_comma;
|
||||
},
|
||||
'.' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_dot;
|
||||
},
|
||||
':' => blk: {
|
||||
index += 1;
|
||||
break :blk .operator_colon;
|
||||
},
|
||||
'!' => blk: {
|
||||
index += 1;
|
||||
switch (text[index]) {
|
||||
'=' => {
|
||||
index += 1;
|
||||
break :blk .operator_compare_not_equal;
|
||||
},
|
||||
else => break :blk .operator_bang,
|
||||
}
|
||||
|
||||
},
|
||||
'=' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_compare_equal;
|
||||
},
|
||||
'>' => b: {
|
||||
index += 1;
|
||||
break :b .operator_switch_case;
|
||||
},
|
||||
else => .operator_assign,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'+' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_add_assign;
|
||||
},
|
||||
else => .operator_add,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'-' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_sub_assign;
|
||||
},
|
||||
else => .operator_minus,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'*' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_mul_assign;
|
||||
},
|
||||
else => .operator_asterisk,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'/' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_div_assign;
|
||||
},
|
||||
else => .operator_div,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'%' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_mod_assign;
|
||||
},
|
||||
else => .operator_mod,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'|' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_or_assign;
|
||||
},
|
||||
else => .operator_bar,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'&' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_and_assign;
|
||||
},
|
||||
else => .operator_ampersand,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'^' => blk: {
|
||||
index += 1;
|
||||
const token_id: Token.Id = switch (text[index]) {
|
||||
'=' => b: {
|
||||
index += 1;
|
||||
break :b .operator_xor_assign;
|
||||
},
|
||||
else => .operator_xor,
|
||||
};
|
||||
|
||||
break :blk token_id;
|
||||
},
|
||||
'?' => blk: {
|
||||
index += 1;
|
||||
|
||||
break :blk .operator_optional;
|
||||
},
|
||||
'$' => blk: {
|
||||
index += 1;
|
||||
|
||||
break :blk .operator_dollar;
|
||||
},
|
||||
else => |ch| {
|
||||
std.debug.panic("NI: '{c}'", .{ch});
|
||||
},
|
||||
};
|
||||
|
||||
const end_index = index;
|
||||
const token_length = end_index - start_index;
|
||||
|
||||
token_buffer.tokens.appendAssumeCapacity(.{
|
||||
.id = token_id,
|
||||
.offset = start_index,
|
||||
.length = token_length,
|
||||
.line = line_index,
|
||||
});
|
||||
const line_offset = token_buffer.line_offsets.items[line_index];
|
||||
const column = start_index - line_offset;
|
||||
logln(.lexer, .new_token, "T at line {}, column {}, byte offset {}, with length {} -line offset: {}- ({s})", .{line_index, column, start_index, token_length, line_offset, @tagName(token_id)});
|
||||
}
|
||||
|
||||
logln(.lexer, .end, "END LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{Token.unwrap(lexer.offset), lexer.line_offset});
|
||||
|
||||
lexer.count = Token.sub(token_buffer.getOffset(), lexer.offset);
|
||||
lexer.line_count = token_buffer.getLineOffset() - lexer.line_offset;
|
||||
|
||||
const time_end = std.time.Instant.now() catch unreachable;
|
||||
lexer.time = time_end.since(time_start);
|
||||
return lexer;
|
||||
}
|
@ -1,265 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log;
|
||||
|
||||
const equal = std.mem.eql;
|
||||
|
||||
const data_structures = @import("../data_structures.zig");
|
||||
const ArrayList = data_structures.ArrayList;
|
||||
const enumFromString = data_structures.enumFromString;
|
||||
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const File = Compilation.File;
|
||||
const logln = Compilation.logln;
|
||||
const fs = @import("../fs.zig");
|
||||
|
||||
// TODO: switch to packed struct when speed is important
|
||||
pub const Token = struct {
|
||||
start: u32,
|
||||
len: u24,
|
||||
id: Id,
|
||||
|
||||
pub const Id = enum(u8) {
|
||||
eof = 0x00,
|
||||
keyword_unsigned_integer = 0x01,
|
||||
keyword_signed_integer = 0x02,
|
||||
identifier = 0x03,
|
||||
number_literal = 0x04,
|
||||
string_literal = 0x05,
|
||||
discard = 0x06,
|
||||
bang = '!', // 0x21
|
||||
hash = '#', // 0x23
|
||||
dollar_sign = '$', // 0x24
|
||||
modulus = '%', // 0x25
|
||||
ampersand = '&', // 0x26
|
||||
left_parenthesis = '(', // 0x28
|
||||
right_parenthesis = ')', // 0x29
|
||||
asterisk = '*', // 0x2a
|
||||
plus = '+', // 0x2b
|
||||
comma = ',', // 0x2c
|
||||
minus = '-', // 0x2d
|
||||
period = '.', // 0x2e
|
||||
slash = '/', // 0x2f
|
||||
colon = ':', // 0x3a
|
||||
semicolon = ';', // 0x3b
|
||||
less = '<', // 0x3c
|
||||
equal = '=', // 0x3d
|
||||
greater = '>', // 0x3e
|
||||
question_mark = '?', // 0x3f
|
||||
at = '@', // 0x40
|
||||
left_bracket = '[', // 0x5b
|
||||
backlash = '\\', // 0x5c
|
||||
right_bracket = ']', // 0x5d
|
||||
caret = '^', // 0x5e
|
||||
underscore = '_', // 0x5f
|
||||
grave = '`', // 0x60
|
||||
left_brace = '{', // 0x7b
|
||||
vertical_bar = '|', // 0x7c
|
||||
right_brace = '}', // 0x7d
|
||||
tilde = '~', // 0x7e
|
||||
fixed_keyword_function = 0x7f,
|
||||
fixed_keyword_const = 0x80,
|
||||
fixed_keyword_var = 0x81,
|
||||
fixed_keyword_void = 0x82,
|
||||
fixed_keyword_noreturn = 0x83,
|
||||
fixed_keyword_comptime = 0x84,
|
||||
fixed_keyword_while = 0x85,
|
||||
fixed_keyword_bool = 0x86,
|
||||
fixed_keyword_true = 0x87,
|
||||
fixed_keyword_false = 0x88,
|
||||
fixed_keyword_fn = 0x89,
|
||||
fixed_keyword_unreachable = 0x8a,
|
||||
fixed_keyword_return = 0x8b,
|
||||
fixed_keyword_ssize = 0x8c,
|
||||
fixed_keyword_usize = 0x8d,
|
||||
fixed_keyword_switch = 0x8e,
|
||||
fixed_keyword_if = 0x8f,
|
||||
fixed_keyword_else = 0x90,
|
||||
fixed_keyword_struct = 0x91,
|
||||
fixed_keyword_enum = 0x92,
|
||||
fixed_keyword_union = 0x93,
|
||||
fixed_keyword_extern = 0x94,
|
||||
fixed_keyword_null = 0x95,
|
||||
fixed_keyword_align = 0x96,
|
||||
fixed_keyword_export = 0x97,
|
||||
fixed_keyword_cc = 0x98,
|
||||
fixed_keyword_for = 0x99,
|
||||
fixed_keyword_undefined = 0x9a,
|
||||
fixed_keyword_break = 0x9b,
|
||||
};
|
||||
|
||||
pub const Index = u32;
|
||||
};
|
||||
|
||||
pub const FixedKeyword = enum {
|
||||
@"comptime",
|
||||
@"const",
|
||||
@"var",
|
||||
void,
|
||||
noreturn,
|
||||
function,
|
||||
@"while",
|
||||
bool,
|
||||
true,
|
||||
false,
|
||||
@"fn",
|
||||
@"unreachable",
|
||||
@"return",
|
||||
ssize,
|
||||
usize,
|
||||
@"switch",
|
||||
@"if",
|
||||
@"else",
|
||||
@"struct",
|
||||
@"enum",
|
||||
@"union",
|
||||
@"extern",
|
||||
null,
|
||||
@"align",
|
||||
@"export",
|
||||
cc,
|
||||
@"for",
|
||||
undefined,
|
||||
@"break",
|
||||
};
|
||||
|
||||
pub const Result = struct {
|
||||
tokens: ArrayList(Token),
|
||||
time: u64,
|
||||
};
|
||||
|
||||
pub const Logger = enum {
|
||||
main,
|
||||
new_token,
|
||||
number_literals,
|
||||
|
||||
pub var bitset = std.EnumSet(Logger).initMany(&.{
|
||||
// .new_token,
|
||||
.number_literals,
|
||||
});
|
||||
};
|
||||
|
||||
pub fn analyze(allocator: Allocator, text: []const u8, file_index: File.Index) !Result {
|
||||
_ = file_index;
|
||||
const time_start = std.time.Instant.now() catch unreachable;
|
||||
var tokens = try ArrayList(Token).initCapacity(allocator, text.len / 8);
|
||||
var index: usize = 0;
|
||||
|
||||
while (index < text.len) {
|
||||
const start_index = index;
|
||||
const start_character = text[index];
|
||||
const token_id: Token.Id = switch (start_character) {
|
||||
'a'...'z', 'A'...'Z', '_' => blk: {
|
||||
while (true) {
|
||||
const ch = text[index];
|
||||
if ((ch >= 'a' and ch <= 'z') or (ch >= 'A' and ch <= 'Z') or ch == '_' or (ch >= '0' and ch <= '9')) {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// const identifier = text[start_index..][0 .. index - start_index];
|
||||
// logln("Identifier: {s}", .{identifier});
|
||||
|
||||
if (start_character == 'u' or start_character == 's') {
|
||||
var index_integer = start_index + 1;
|
||||
while (text[index_integer] >= '0' and text[index_integer] <= '9') {
|
||||
index_integer += 1;
|
||||
}
|
||||
|
||||
if (index_integer == index) {
|
||||
const id: Token.Id = switch (start_character) {
|
||||
'u' => .keyword_unsigned_integer,
|
||||
's' => .keyword_signed_integer,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
break :blk id;
|
||||
}
|
||||
}
|
||||
|
||||
const string = text[start_index..][0 .. index - start_index];
|
||||
break :blk if (enumFromString(FixedKeyword, string)) |fixed_keyword| switch (fixed_keyword) {
|
||||
inline else => |comptime_fixed_keyword| @field(Token.Id, "fixed_keyword_" ++ @tagName(comptime_fixed_keyword)),
|
||||
} else if (equal(u8, string, "_")) .discard else .identifier;
|
||||
},
|
||||
'0'...'9' => blk: {
|
||||
// Detect other non-decimal literals
|
||||
if (text[index] == '0' and index + 1 < text.len) {
|
||||
logln(.lexer, .number_literals, "Number starts with 0. Checking for non-decimal literals...", .{});
|
||||
if (text[index + 1] == 'x') {
|
||||
logln(.lexer, .number_literals, "Hex", .{});
|
||||
index += 2;
|
||||
} else if (text[index + 1] == 'b') {
|
||||
logln(.lexer, .number_literals, "Bin", .{});
|
||||
index += 2;
|
||||
} else if (text[index + 1] == 'o') {
|
||||
logln(.lexer, .number_literals, "Decimal", .{});
|
||||
index += 2;
|
||||
}
|
||||
}
|
||||
|
||||
while (text[index] >= '0' and text[index] <= '9' or text[index] >= 'a' and text[index] <= 'f' or text[index] >= 'A' and text[index] <= 'F') {
|
||||
index += 1;
|
||||
}
|
||||
|
||||
break :blk .number_literal;
|
||||
},
|
||||
'\'' => {
|
||||
unreachable;
|
||||
},
|
||||
'"' => blk: {
|
||||
index += 1;
|
||||
|
||||
while (true) {
|
||||
if (text[index] == '"' and text[index - 1] != '"') {
|
||||
break;
|
||||
}
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
index += 1;
|
||||
|
||||
break :blk .string_literal;
|
||||
},
|
||||
' ', '\n', '\r', '\t' => {
|
||||
index += 1;
|
||||
continue;
|
||||
},
|
||||
'(', ')', '{', '}', '[', ']', '=', ';', '#', '@', ',', '.', ':', '>', '<', '!', '+', '-', '*', '\\', '/', '&', '|', '^', '?', '$' => |operator| blk: {
|
||||
index += 1;
|
||||
break :blk @enumFromInt(operator);
|
||||
},
|
||||
else => |ch| {
|
||||
std.debug.panic("NI: '{c}'", .{ch});
|
||||
},
|
||||
};
|
||||
|
||||
const end_index = index;
|
||||
const token = Token{
|
||||
.start = @intCast(start_index),
|
||||
.len = @intCast(end_index - start_index),
|
||||
.id = token_id,
|
||||
};
|
||||
|
||||
logln(.lexer, .new_token, "New token {s} added: {s}", .{ @tagName(token.id), text[token.start..][0..token.len] });
|
||||
|
||||
try tokens.append(allocator, token);
|
||||
}
|
||||
|
||||
for (tokens.items, 0..) |token, i| {
|
||||
logln(.lexer, .main, "#{} {s}\n", .{ i, @tagName(token.id) });
|
||||
}
|
||||
|
||||
const time_end = std.time.Instant.now() catch unreachable;
|
||||
const time = time_end.since(time_start);
|
||||
|
||||
return .{
|
||||
.tokens = tokens,
|
||||
.time = time,
|
||||
};
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -5,10 +5,8 @@ const Compilation = @import("Compilation.zig");
|
||||
pub const panic = Compilation.panic;
|
||||
|
||||
pub fn main() !void {
|
||||
const GPA = std.heap.GeneralPurposeAllocator(.{});
|
||||
var gpa = GPA{};
|
||||
|
||||
try Compilation.init(gpa.allocator());
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
try Compilation.init(arena_allocator.allocator());
|
||||
}
|
||||
|
||||
test {
|
||||
|
231
build.zig
231
build.zig
@ -3,19 +3,238 @@ var all: bool = false;
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
all = b.option(bool, "all", "All") orelse false;
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimization = b.standardOptimizeOption(.{});
|
||||
const use_llvm = b.option(bool, "use_llvm", "Use LLVM as the backend for generate the compiler binary") orelse true;
|
||||
const llvm_debug = b.option(bool, "llvm_debug", "Use LLVM in the debug version") orelse false;
|
||||
const llvm_debug_path = b.option([]const u8, "llvm_debug_path", "LLVM debug path") orelse "../dev/llvm-17-static-debug";
|
||||
const llvm_release_path = b.option([]const u8, "llvm_release_path", "LLVM release path") orelse "../dev/llvm-17-static-release";
|
||||
const target_query = try std.zig.CrossTarget.parse(.{
|
||||
.arch_os_abi = "native-linux-musl",
|
||||
});
|
||||
const target = b.resolveTargetQuery(target_query);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "nat",
|
||||
.root_source_file = .{ .path = "bootstrap/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimization,
|
||||
.use_llvm = use_llvm,
|
||||
.use_lld = false,
|
||||
.use_llvm = true,
|
||||
.use_lld = true,
|
||||
});
|
||||
exe.unwind_tables = false;
|
||||
exe.omit_frame_pointer = false;
|
||||
exe.formatted_panics = false;
|
||||
exe.root_module.unwind_tables = false;
|
||||
exe.root_module.omit_frame_pointer = false;
|
||||
|
||||
const llvm_dir = if (llvm_debug) llvm_debug_path else llvm_release_path;
|
||||
const llvm_include_dir = try std.mem.concat(b.allocator, u8, &.{ llvm_dir, "/include" });
|
||||
const llvm_lib_dir = try std.mem.concat(b.allocator, u8, &.{ llvm_dir, "/lib" });
|
||||
|
||||
exe.linkLibC();
|
||||
exe.linkLibCpp();
|
||||
|
||||
exe.addIncludePath(std.Build.LazyPath.relative(llvm_include_dir));
|
||||
exe.addCSourceFile(.{
|
||||
.file = std.Build.LazyPath.relative("bootstrap/backend/llvm.cpp"),
|
||||
.flags = &.{"-g"},
|
||||
});
|
||||
|
||||
const llvm_libraries = [_][]const u8{
|
||||
"libLLVMAArch64AsmParser.a",
|
||||
"libLLVMAArch64CodeGen.a",
|
||||
"libLLVMAArch64Desc.a",
|
||||
"libLLVMAArch64Disassembler.a",
|
||||
"libLLVMAArch64Info.a",
|
||||
"libLLVMAArch64Utils.a",
|
||||
"libLLVMAggressiveInstCombine.a",
|
||||
"libLLVMAMDGPUAsmParser.a",
|
||||
"libLLVMAMDGPUCodeGen.a",
|
||||
"libLLVMAMDGPUDesc.a",
|
||||
"libLLVMAMDGPUDisassembler.a",
|
||||
"libLLVMAMDGPUInfo.a",
|
||||
"libLLVMAMDGPUTargetMCA.a",
|
||||
"libLLVMAMDGPUUtils.a",
|
||||
"libLLVMAnalysis.a",
|
||||
"libLLVMARMAsmParser.a",
|
||||
"libLLVMARMCodeGen.a",
|
||||
"libLLVMARMDesc.a",
|
||||
"libLLVMARMDisassembler.a",
|
||||
"libLLVMARMInfo.a",
|
||||
"libLLVMARMUtils.a",
|
||||
"libLLVMAsmParser.a",
|
||||
"libLLVMAsmPrinter.a",
|
||||
"libLLVMAVRAsmParser.a",
|
||||
"libLLVMAVRCodeGen.a",
|
||||
"libLLVMAVRDesc.a",
|
||||
"libLLVMAVRDisassembler.a",
|
||||
"libLLVMAVRInfo.a",
|
||||
"libLLVMBinaryFormat.a",
|
||||
"libLLVMBitReader.a",
|
||||
"libLLVMBitstreamReader.a",
|
||||
"libLLVMBitWriter.a",
|
||||
"libLLVMBPFAsmParser.a",
|
||||
"libLLVMBPFCodeGen.a",
|
||||
"libLLVMBPFDesc.a",
|
||||
"libLLVMBPFDisassembler.a",
|
||||
"libLLVMBPFInfo.a",
|
||||
"libLLVMCFGuard.a",
|
||||
"libLLVMCFIVerify.a",
|
||||
"libLLVMCodeGen.a",
|
||||
"libLLVMCodeGenTypes.a",
|
||||
"libLLVMCore.a",
|
||||
"libLLVMCoroutines.a",
|
||||
"libLLVMCoverage.a",
|
||||
"libLLVMDebugInfoBTF.a",
|
||||
"libLLVMDebugInfoCodeView.a",
|
||||
"libLLVMDebuginfod.a",
|
||||
"libLLVMDebugInfoDWARF.a",
|
||||
"libLLVMDebugInfoGSYM.a",
|
||||
"libLLVMDebugInfoLogicalView.a",
|
||||
"libLLVMDebugInfoMSF.a",
|
||||
"libLLVMDebugInfoPDB.a",
|
||||
"libLLVMDemangle.a",
|
||||
"libLLVMDiff.a",
|
||||
"libLLVMDlltoolDriver.a",
|
||||
"libLLVMDWARFLinker.a",
|
||||
"libLLVMDWARFLinkerParallel.a",
|
||||
"libLLVMDWP.a",
|
||||
"libLLVMExecutionEngine.a",
|
||||
"libLLVMExtensions.a",
|
||||
"libLLVMFileCheck.a",
|
||||
"libLLVMFrontendHLSL.a",
|
||||
"libLLVMFrontendOpenACC.a",
|
||||
"libLLVMFrontendOpenMP.a",
|
||||
"libLLVMFuzzerCLI.a",
|
||||
"libLLVMFuzzMutate.a",
|
||||
"libLLVMGlobalISel.a",
|
||||
"libLLVMHexagonAsmParser.a",
|
||||
"libLLVMHexagonCodeGen.a",
|
||||
"libLLVMHexagonDesc.a",
|
||||
"libLLVMHexagonDisassembler.a",
|
||||
"libLLVMHexagonInfo.a",
|
||||
"libLLVMInstCombine.a",
|
||||
"libLLVMInstrumentation.a",
|
||||
"libLLVMInterfaceStub.a",
|
||||
"libLLVMInterpreter.a",
|
||||
"libLLVMipo.a",
|
||||
"libLLVMIRPrinter.a",
|
||||
"libLLVMIRReader.a",
|
||||
"libLLVMJITLink.a",
|
||||
"libLLVMLanaiAsmParser.a",
|
||||
"libLLVMLanaiCodeGen.a",
|
||||
"libLLVMLanaiDesc.a",
|
||||
"libLLVMLanaiDisassembler.a",
|
||||
"libLLVMLanaiInfo.a",
|
||||
"libLLVMLibDriver.a",
|
||||
"libLLVMLineEditor.a",
|
||||
"libLLVMLinker.a",
|
||||
"libLLVMLoongArchAsmParser.a",
|
||||
"libLLVMLoongArchCodeGen.a",
|
||||
"libLLVMLoongArchDesc.a",
|
||||
"libLLVMLoongArchDisassembler.a",
|
||||
"libLLVMLoongArchInfo.a",
|
||||
"libLLVMLTO.a",
|
||||
"libLLVMMC.a",
|
||||
"libLLVMMCA.a",
|
||||
"libLLVMMCDisassembler.a",
|
||||
"libLLVMMCJIT.a",
|
||||
"libLLVMMCParser.a",
|
||||
"libLLVMMipsAsmParser.a",
|
||||
"libLLVMMipsCodeGen.a",
|
||||
"libLLVMMipsDesc.a",
|
||||
"libLLVMMipsDisassembler.a",
|
||||
"libLLVMMipsInfo.a",
|
||||
"libLLVMMIRParser.a",
|
||||
"libLLVMMSP430AsmParser.a",
|
||||
"libLLVMMSP430CodeGen.a",
|
||||
"libLLVMMSP430Desc.a",
|
||||
"libLLVMMSP430Disassembler.a",
|
||||
"libLLVMMSP430Info.a",
|
||||
"libLLVMNVPTXCodeGen.a",
|
||||
"libLLVMNVPTXDesc.a",
|
||||
"libLLVMNVPTXInfo.a",
|
||||
"libLLVMObjCARCOpts.a",
|
||||
"libLLVMObjCopy.a",
|
||||
"libLLVMObject.a",
|
||||
"libLLVMObjectYAML.a",
|
||||
"libLLVMOption.a",
|
||||
"libLLVMOrcJIT.a",
|
||||
"libLLVMOrcShared.a",
|
||||
"libLLVMOrcTargetProcess.a",
|
||||
"libLLVMPasses.a",
|
||||
"libLLVMPowerPCAsmParser.a",
|
||||
"libLLVMPowerPCCodeGen.a",
|
||||
"libLLVMPowerPCDesc.a",
|
||||
"libLLVMPowerPCDisassembler.a",
|
||||
"libLLVMPowerPCInfo.a",
|
||||
"libLLVMProfileData.a",
|
||||
"libLLVMRemarks.a",
|
||||
"libLLVMRISCVAsmParser.a",
|
||||
"libLLVMRISCVCodeGen.a",
|
||||
"libLLVMRISCVDesc.a",
|
||||
"libLLVMRISCVDisassembler.a",
|
||||
"libLLVMRISCVInfo.a",
|
||||
"libLLVMRISCVTargetMCA.a",
|
||||
"libLLVMRuntimeDyld.a",
|
||||
"libLLVMScalarOpts.a",
|
||||
"libLLVMSelectionDAG.a",
|
||||
"libLLVMSparcAsmParser.a",
|
||||
"libLLVMSparcCodeGen.a",
|
||||
"libLLVMSparcDesc.a",
|
||||
"libLLVMSparcDisassembler.a",
|
||||
"libLLVMSparcInfo.a",
|
||||
"libLLVMSupport.a",
|
||||
"libLLVMSymbolize.a",
|
||||
"libLLVMSystemZAsmParser.a",
|
||||
"libLLVMSystemZCodeGen.a",
|
||||
"libLLVMSystemZDesc.a",
|
||||
"libLLVMSystemZDisassembler.a",
|
||||
"libLLVMSystemZInfo.a",
|
||||
"libLLVMTableGen.a",
|
||||
"libLLVMTableGenCommon.a",
|
||||
"libLLVMTableGenGlobalISel.a",
|
||||
"libLLVMTarget.a",
|
||||
"libLLVMTargetParser.a",
|
||||
"libLLVMTextAPI.a",
|
||||
"libLLVMTransformUtils.a",
|
||||
"libLLVMVEAsmParser.a",
|
||||
"libLLVMVECodeGen.a",
|
||||
"libLLVMVectorize.a",
|
||||
"libLLVMVEDesc.a",
|
||||
"libLLVMVEDisassembler.a",
|
||||
"libLLVMVEInfo.a",
|
||||
"libLLVMWebAssemblyAsmParser.a",
|
||||
"libLLVMWebAssemblyCodeGen.a",
|
||||
"libLLVMWebAssemblyDesc.a",
|
||||
"libLLVMWebAssemblyDisassembler.a",
|
||||
"libLLVMWebAssemblyInfo.a",
|
||||
"libLLVMWebAssemblyUtils.a",
|
||||
"libLLVMWindowsDriver.a",
|
||||
"libLLVMWindowsManifest.a",
|
||||
"libLLVMX86AsmParser.a",
|
||||
"libLLVMX86CodeGen.a",
|
||||
"libLLVMX86Desc.a",
|
||||
"libLLVMX86Disassembler.a",
|
||||
"libLLVMX86Info.a",
|
||||
"libLLVMX86TargetMCA.a",
|
||||
"libLLVMXCoreCodeGen.a",
|
||||
"libLLVMXCoreDesc.a",
|
||||
"libLLVMXCoreDisassembler.a",
|
||||
"libLLVMXCoreInfo.a",
|
||||
"libLLVMXRay.a",
|
||||
// Zlib
|
||||
"libz.a",
|
||||
"libzstd.a",
|
||||
//LLD
|
||||
"liblldCOFF.a",
|
||||
"liblldCommon.a",
|
||||
"liblldELF.a",
|
||||
"liblldMachO.a",
|
||||
"liblldMinGW.a",
|
||||
"liblldWasm.a",
|
||||
};
|
||||
|
||||
inline for (llvm_libraries) |llvm_library| {
|
||||
exe.addObjectFile(std.Build.LazyPath.relative(try std.mem.concat(b.allocator, u8, &.{ llvm_lib_dir, "/", llvm_library })));
|
||||
}
|
||||
|
||||
|
||||
const install_exe = b.addInstallArtifact(exe, .{});
|
||||
b.getInstallStep().dependOn(&install_exe.step);
|
||||
|
85
ci.sh
85
ci.sh
@ -1,8 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
argument_count=$#;
|
||||
extra_args=""
|
||||
use_debug="true"
|
||||
if [ $argument_count -ne 0 ]; then
|
||||
llvm_debug_path=$1
|
||||
llvm_release_path=$2
|
||||
use_debug="false"
|
||||
extra_args="-Dllvm_debug_path=$llvm_debug_path -Dllvm_release_path=$llvm_release_path"
|
||||
fi
|
||||
|
||||
echo -e "\e[90mCompiling Nativity with Zig...\e[0m"
|
||||
nativity_use_llvm=true
|
||||
zig build -Duse_llvm=$nativity_use_llvm
|
||||
zig build -Dllvm_debug=$use_debug $extra_args
|
||||
if [[ "$?" != 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
failed_test_count=0
|
||||
passed_test_count=0
|
||||
test_directory_name=test
|
||||
@ -57,41 +68,41 @@ do
|
||||
test_i=$(($test_i + 1))
|
||||
done
|
||||
|
||||
for integral_test_case in $integral_test_directory_files
|
||||
do
|
||||
MY_TESTNAME=${integral_test_case##*/}
|
||||
cd test/integral/$MY_TESTNAME
|
||||
$nat_compiler
|
||||
|
||||
if [[ "$?" == "0" ]]; then
|
||||
passed_compilation_count=$(($passed_compilation_count + 1))
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
nat/$MY_TESTNAME
|
||||
|
||||
if [[ "$?" == "0" ]]; then
|
||||
passed_test_count=$(($passed_test_count + 1))
|
||||
result="\e[32mPASSED\e[0m"
|
||||
else
|
||||
failed_test_count=$(($failed_test_count + 1))
|
||||
result="\e[31mFAILED\e[0m"
|
||||
failed_tests+=("$test_i. $MY_TESTNAME")
|
||||
fi
|
||||
|
||||
ran_test_count=$(($ran_test_count + 1))
|
||||
else
|
||||
result="\e[31mOS NOT SUPPORTED\e[0m"
|
||||
fi
|
||||
else
|
||||
failed_compilation_count=$(($failed_compilation_count + 1))
|
||||
result="\e[31mCOMPILATION FAILURE\e[0m"
|
||||
failed_compilations+=("$test_i. $MY_TESTNAME")
|
||||
fi
|
||||
|
||||
echo -e "[$test_i/$total_test_count] [$result] [INTEGRAL] $MY_TESTNAME"
|
||||
|
||||
test_i=$(($test_i + 1))
|
||||
cd $my_current_directory
|
||||
done
|
||||
# for integral_test_case in $integral_test_directory_files
|
||||
# do
|
||||
# MY_TESTNAME=${integral_test_case##*/}
|
||||
# cd test/integral/$MY_TESTNAME
|
||||
# $nat_compiler
|
||||
#
|
||||
# if [[ "$?" == "0" ]]; then
|
||||
# passed_compilation_count=$(($passed_compilation_count + 1))
|
||||
# if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
# nat/$MY_TESTNAME
|
||||
#
|
||||
# if [[ "$?" == "0" ]]; then
|
||||
# passed_test_count=$(($passed_test_count + 1))
|
||||
# result="\e[32mPASSED\e[0m"
|
||||
# else
|
||||
# failed_test_count=$(($failed_test_count + 1))
|
||||
# result="\e[31mFAILED\e[0m"
|
||||
# failed_tests+=("$test_i. $MY_TESTNAME")
|
||||
# fi
|
||||
#
|
||||
# ran_test_count=$(($ran_test_count + 1))
|
||||
# else
|
||||
# result="\e[31mOS NOT SUPPORTED\e[0m"
|
||||
# fi
|
||||
# else
|
||||
# failed_compilation_count=$(($failed_compilation_count + 1))
|
||||
# result="\e[31mCOMPILATION FAILURE\e[0m"
|
||||
# failed_compilations+=("$test_i. $MY_TESTNAME")
|
||||
# fi
|
||||
#
|
||||
# echo -e "[$test_i/$total_test_count] [$result] [INTEGRAL] $MY_TESTNAME"
|
||||
#
|
||||
# test_i=$(($test_i + 1))
|
||||
# cd $my_current_directory
|
||||
# done
|
||||
|
||||
printf "\n"
|
||||
echo -e "\e[35m[SUMMARY]\e[0m"
|
||||
|
@ -12,7 +12,7 @@ const Executable = struct{
|
||||
const compile = fn(executable: Executable) bool {
|
||||
const argument_count = std.start.argument_count;
|
||||
const argument_values = std.start.argument_values;
|
||||
assert(ok = argument_count == 3);
|
||||
assert(ok = argument_count >= 3);
|
||||
const compiler_path = argument_values[2];
|
||||
|
||||
const result = executable.compile_with_compiler_path(compiler_path);
|
||||
|
@ -17,5 +17,4 @@ const Abi = enum{
|
||||
|
||||
const CallingConvention = enum{
|
||||
system_v,
|
||||
naked,
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ const system = switch (current) {
|
||||
|
||||
const exit = fn(exit_code: s32) noreturn {
|
||||
switch (current) {
|
||||
.linux => _ = #syscall(#cast(linux.Syscall.exit_group), exit_code),
|
||||
.linux => _ = #syscall(#cast(linux.Syscall.exit_group), #cast(exit_code)),
|
||||
.macos => macos.exit(exit_code),
|
||||
.windows => windows.ExitProcess(exit_code),
|
||||
}
|
||||
@ -30,7 +30,7 @@ const FileDescriptor = struct{
|
||||
switch (current) {
|
||||
.linux => {
|
||||
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
||||
if (linux.unwrapSyscall(syscall_result = #syscall(#cast(linux.Syscall.read), file_descriptor.handle, #cast(bytes.ptr), len))) |byte_count| {
|
||||
if (linux.unwrapSyscall(syscall_result = #syscall(#cast(linux.Syscall.read), #cast(file_descriptor.handle), #cast(bytes.ptr), len))) |byte_count| {
|
||||
return byte_count;
|
||||
} else {
|
||||
return null;
|
||||
@ -47,7 +47,7 @@ const FileDescriptor = struct{
|
||||
switch (current) {
|
||||
.linux => {
|
||||
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
||||
const raw_result = #syscall(#cast(linux.Syscall.write), file_descriptor.handle, #cast(bytes.ptr), len);
|
||||
const raw_result = #syscall(#cast(linux.Syscall.write), #cast(file_descriptor.handle), #cast(bytes.ptr), len);
|
||||
if (linux.unwrapSyscall(syscall_result = raw_result)) |byte_count| {
|
||||
return byte_count;
|
||||
} else {
|
||||
|
@ -411,7 +411,7 @@ const get_map_flags = fn(flags: std.os.MapFlags) MapFlags{
|
||||
}
|
||||
|
||||
const mmap = fn(address: ?[&]u8, length: usize, protection_flags: ProtectionFlags, map_flags: MapFlags, fd: s32, offset: u64) usize {
|
||||
const result = #syscall(#cast(Syscall.mmap), #cast(address), length, #cast(protection_flags), #cast(map_flags), fd, offset);
|
||||
const result = #syscall(#cast(Syscall.mmap), #cast(address), length, #cast(protection_flags), #cast(map_flags), #cast(fd), offset);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ comptime {
|
||||
}
|
||||
}
|
||||
|
||||
const _start = fn () noreturn export cc(.naked) {
|
||||
const _start = fn naked, export () noreturn {
|
||||
#asm({
|
||||
xor ebp, ebp;
|
||||
mov rdi, rsp;
|
||||
@ -21,7 +21,7 @@ var argument_count: usize = 0;
|
||||
var argument_values: [&]const [&:0]const u8 = undefined;
|
||||
var environment_values: [&:null]const ?[&:null]const u8 = undefined;
|
||||
|
||||
const start = fn(argc_argv_address: usize) noreturn export {
|
||||
const start = fn export (argc_argv_address: usize) noreturn {
|
||||
var argument_address_iterator = argc_argv_address;
|
||||
const argument_count_ptr: &usize = #cast(argument_address_iterator);
|
||||
argument_count = argument_count_ptr.@;
|
||||
@ -33,6 +33,6 @@ const start = fn(argc_argv_address: usize) noreturn export {
|
||||
std.os.exit(exit_code = result);
|
||||
}
|
||||
|
||||
const main = fn(argc: s32, argv: [&:null]?[&:null]u8, env: [&:null]?[&:null]u8) s32 export {
|
||||
const main = fn export (argc: s32, argv: [&:null]?[&:null]u8, env: [&:null]?[&:null]u8) s32 {
|
||||
return #import("main").main();
|
||||
}
|
||||
|
@ -21,6 +21,38 @@ const print = fn(bytes: []const u8) void {
|
||||
_ = file_writer.writeAll(bytes);
|
||||
}
|
||||
|
||||
const format_usize = fn(n: usize, buffer: &[65]u8) []u8 {
|
||||
var index: usize = buffer.len;
|
||||
var absolute = n;
|
||||
|
||||
while (true) {
|
||||
const digit: u8 = #cast(absolute % 10);
|
||||
index -= 1;
|
||||
buffer[index] = '0' + digit;
|
||||
absolute /= 10;
|
||||
|
||||
if (absolute == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer[index..];
|
||||
}
|
||||
|
||||
const print_usize = fn(n: usize) void {
|
||||
var buffer: [65]u8 = undefined;
|
||||
const bytes = format_usize(n, buffer = buffer.&);
|
||||
const file_descriptor = os.StdFileDescriptor.get(descriptor = .stdout);
|
||||
const file_writer = FileWriter{
|
||||
.descriptor = file_descriptor,
|
||||
};
|
||||
_ = file_writer.writeAll(bytes);
|
||||
}
|
||||
|
||||
const print_u8 = fn(n: u8) void {
|
||||
print_usize(n);
|
||||
}
|
||||
|
||||
const Allocator = struct {
|
||||
handler: &const fn(allocator: &Allocator, old_ptr: ?[&]const u8, old_size: usize, new_size: usize, alignment: u16) ?[&]u8,
|
||||
|
||||
@ -135,6 +167,25 @@ const copy_bytes = fn(destination: []u8, source: []const u8) void {
|
||||
}
|
||||
}
|
||||
|
||||
const concatenate_bytes = fn(allocator: &Allocator, slices: []const []const u8) ?[]u8 {
|
||||
var total_byte_count: usize = 0;
|
||||
for (slices) |slice| {
|
||||
total_byte_count += slice.len;
|
||||
}
|
||||
|
||||
if (allocator.allocate(total_byte_count, 1)) |bytes| {
|
||||
var offset: usize = 0;
|
||||
for (slice) |slice| {
|
||||
copy_bytes(bytes[offset..][0..slice.len], slice);
|
||||
offset += slice.len;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const Target = struct {
|
||||
cpu: builtin.Cpu,
|
||||
os: builtin.Os,
|
||||
|
12
todo_test/standalone/break/main.nat
Normal file
12
todo_test/standalone/break/main.nat
Normal file
@ -0,0 +1,12 @@
|
||||
const main = fn() s32 {
|
||||
var i: s32 = 0;
|
||||
const j: s32 = 5;
|
||||
for (0..10) |_| {
|
||||
if (i == j) {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return i - j;
|
||||
}
|
3
todo_test/standalone/first/main.nat
Normal file
3
todo_test/standalone/first/main.nat
Normal file
@ -0,0 +1,3 @@
|
||||
const main = fn() s32 {
|
||||
return 0;
|
||||
}
|
30
todo_test/standalone/foreach_slice/main.nat
Normal file
30
todo_test/standalone/foreach_slice/main.nat
Normal file
@ -0,0 +1,30 @@
|
||||
const std = #import("std");
|
||||
const print = std.print;
|
||||
|
||||
const count_slice_byte_count = fn(slices: []const []const u8) usize {
|
||||
var byte_count: usize = 0;
|
||||
|
||||
for (slices) |slice| {
|
||||
byte_count += slice.len;
|
||||
}
|
||||
|
||||
return byte_count;
|
||||
}
|
||||
|
||||
const print_values = fn(slice: []const u8) void {
|
||||
for (slice, 0..) |value, index| {
|
||||
std.print_usize(n = index);
|
||||
std.print(bytes = ": ");
|
||||
std.print_u8(n = value);
|
||||
std.print(bytes = "\n");
|
||||
}
|
||||
}
|
||||
|
||||
const main = fn () s32 {
|
||||
const a = [_]u8{1, 1, 4, 5, 6};
|
||||
const b = [_]u8{1, 4, 6};
|
||||
const expected_result: usize = a.len + b.len;
|
||||
const result = count_slice_byte_count(slices = .{a.&, b.&}.&);
|
||||
print_values(slice = a.&);
|
||||
return #cast(expected_result - result);
|
||||
}
|
8
todo_test/standalone/optional_wrap/main.nat
Normal file
8
todo_test/standalone/optional_wrap/main.nat
Normal file
@ -0,0 +1,8 @@
|
||||
const foo = fn(slice: []u8) ?[]u8 {
|
||||
return slice[0..1];
|
||||
}
|
||||
const main = fn() s32 {
|
||||
_ = foo(slice = .{ 0, 1, 2, 3 }.&);
|
||||
|
||||
return 0;
|
||||
}
|
@ -2,5 +2,6 @@ const main = fn() s32 {
|
||||
const a: u32 = 0xffff;
|
||||
const b: u32 = 0xffff0000;
|
||||
const c: u32 = 0xffffffff;
|
||||
return c - (a | b);
|
||||
const result = c - (a | b);
|
||||
return #cast(result);
|
||||
}
|
14
todo_test/standalone/slice/main.nat
Normal file
14
todo_test/standalone/slice/main.nat
Normal file
@ -0,0 +1,14 @@
|
||||
const main = fn () s32{
|
||||
const a: [4]u8 = .{1, 2, 3, 4};
|
||||
const b: []const []const u8 = .{a.&}.&;
|
||||
|
||||
var sum: u8 = 0;
|
||||
|
||||
for (b) |b_slice| {
|
||||
for (b_slice) |a_element| {
|
||||
sum += a_element;
|
||||
}
|
||||
}
|
||||
|
||||
return #cast(sum - 10);
|
||||
}
|
6
todo_test/standalone/slice2/main.nat
Normal file
6
todo_test/standalone/slice2/main.nat
Normal file
@ -0,0 +1,6 @@
|
||||
const main = fn () s32{
|
||||
const a: [4]u8 = .{1, 2, 3, 4};
|
||||
const b: []const []const u8 = .{a.&}.&;
|
||||
|
||||
return #cast(b[0][0] - 1);
|
||||
}
|
10
todo_test/standalone/slice_expression/main.nat
Normal file
10
todo_test/standalone/slice_expression/main.nat
Normal file
@ -0,0 +1,10 @@
|
||||
const main = fn () s32 {
|
||||
_ = foo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const foo = fn () []u8 {
|
||||
var buffer: [5]u8 = undefined;
|
||||
const buffer_ptr: &[5]u8 = buffer.&;
|
||||
return buffer_ptr[2..];
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user