Skip to content

Commit

Permalink
Implement array model for XSharp
Browse files Browse the repository at this point in the history
  • Loading branch information
XChy committed May 23, 2023
1 parent 700dfe1 commit dff8655
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 35 deletions.
12 changes: 11 additions & 1 deletion LLVMIR/ClassProxy/IndexProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ValueAndType CodeGenProxy<IndexNode>::codeGen(IndexNode *ast,
const Generator &generator)
{
auto [index, index_type] = generator(ast->index());

auto [indexed, indexed_type] =
deReference(generator(ast->operand()), helper);

Expand All @@ -33,8 +34,17 @@ ValueAndType CodeGenProxy<IndexNode>::codeGen(IndexNode *ast,
return {nullptr, nullptr};
}

auto array_struct_type = indexed->getType()->getContainedType(0);

llvm::Value *element_ptr_ptr =
helper->llvm_builder.CreateStructGEP(array_struct_type, indexed, 1);

llvm::Value *element_ptr_head = helper->llvm_builder.CreateLoad(
element_ptr_ptr->getType()->getContainedType(0), element_ptr_ptr);

llvm::Value *element = helper->llvm_builder.CreateInBoundsGEP(
castToLLVM(indexed_type->elementType(), helper->llvm_ctx), indexed,
element_ptr_head->getType()->getContainedType(0), element_ptr_head,
index, ast->dump().toStdString());

return {element, getReferenceType(indexed_type->elementType())};
}
34 changes: 27 additions & 7 deletions LLVMIR/CodeGenProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,38 @@ ValueAndType CodeGenProxy<StringNode>::codeGen(StringNode* ast,
CodeGenContext* helper,
const Generator& generator)
{
auto llvm_array_type = (llvm::ArrayType*)castToLLVM(
XSharp::getArrayType(Types::get("char"), 1), helper->llvm_ctx);
auto x_array_type = XSharp::getArrayType(Types::get("char"), 1);
auto llvm_array_type = castToLLVM(x_array_type, helper->llvm_ctx);

llvm::StructType* array_struct_type =
(llvm::StructType*)llvm_array_type->getContainedType(0);

llvm::ArrayType* array_data_type = llvm::ArrayType::get(
castToLLVM(x_array_type->elementType(), helper->llvm_ctx),
ast->value().size());

std::vector<llvm::Constant*> chars;
for (int i = 0; i <= ast->value().size(); ++i) {

for (int i = 0; i < ast->value().size(); ++i) {
chars.push_back(helper->llvm_builder.getInt(
llvm::APInt(16, ast->value()[i].value())));
}

llvm::Constant* data = llvm::ConstantArray::get(llvm_array_type, chars);
llvm::GlobalVariable* glob =
new llvm::GlobalVariable(helper->module, data->getType(), true,
llvm::GlobalValue::ExternalLinkage, data);
llvm::ConstantInt* length_data = llvm::ConstantInt::get(
helper->llvm_ctx, llvm::APInt(64, ast->value().size()));

llvm::Constant* chars_data =
llvm::ConstantArray::get(array_data_type, chars);
llvm::GlobalVariable* glob_chars = new llvm::GlobalVariable(
helper->module, chars_data->getType(), true,
llvm::GlobalValue::ExternalLinkage, chars_data);

llvm::Constant* array_data =
llvm::ConstantStruct::get(array_struct_type, {length_data, glob_chars});

llvm::GlobalVariable* glob = new llvm::GlobalVariable(
helper->module, array_data->getType(), true,
llvm::GlobalValue::ExternalLinkage, array_data);

return {glob, XSharp::getArrayType(Types::get("char"), 1)};
}
Expand Down
13 changes: 11 additions & 2 deletions LLVMIR/LLVMTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Type.h>
#include <cstddef>
#include <vector>
#include "XSharp/Class/XClass.h"
#include "XSharp/Types/TypeSystem.h"

namespace XSharp {
namespace LLVMCodeGen {
Expand Down Expand Up @@ -54,12 +56,19 @@ llvm::Type* castToLLVM(XSharp::Type* type, llvm::LLVMContext& context)
llvmTypesForParams, false);
}

case Type::Array:
case Type::Array: {
// Allocate XSharp's array on heap
// So the type of array is the pointer type of its element
return llvm::PointerType::get(
auto pointerToElements = llvm::PointerType::get(
castToLLVM(type->elementType(), context), 0);

auto structType = llvm::StructType::get(
context,
std::vector<llvm::Type*>{castToLLVM(getI64Type(), context),
pointerToElements});
return structType->getPointerTo();
}

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

Expand Down
25 changes: 22 additions & 3 deletions LLVMIR/Utils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "Utils.h"
#include <llvm/IR/Value.h>
#include "LLVMIR/LLVMTypes.h"
#include "XSharp/Types/Type.h"
#include "XSharp/Types/TypeSystem.h"
#include "XSharp/XString.h"
Expand Down Expand Up @@ -36,8 +37,11 @@ llvm::Value* genArrayMalloc(CodeGenContext* helper, XSharp::Type* type,
auto& context = helper->llvm_ctx;
llvm::FunctionCallee newFunc = module.getOrInsertFunction(
"GC_new_object",
llvm::FunctionType::get(castToLLVM(type, context),
{llvm::Type::getInt64Ty(context)}, false));
llvm::FunctionType::get(
castToLLVM(type->elementType(), context)->getPointerTo(),
{llvm::Type::getInt64Ty(context)}, false));

auto array_struct_type = castToLLVM(type, context)->getContainedType(0);

if (type->isArray()) {
llvm::Value* sizeofElement = llvm::ConstantInt::get(
Expand All @@ -46,7 +50,22 @@ llvm::Value* genArrayMalloc(CodeGenContext* helper, XSharp::Type* type,
llvm::Value* sizeofArray =
helper->llvm_builder.CreateMul(element_count, sizeofElement);

return helper->llvm_builder.CreateCall(newFunc, {sizeofArray});
llvm::Value* array_value =
helper->llvm_builder.CreateAlloca(array_struct_type);

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

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

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

helper->llvm_builder.CreateStore(sizeofElement, length_ptr);
helper->llvm_builder.CreateStore(elements_ptr, elements_ptr_ptr);

return array_value;

} else {
helper->error("Do not support 'new' operator for {}", type->typeName());
Expand Down
2 changes: 1 addition & 1 deletion XSharpRuntime/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

struct xarray {
int64_t length;
char elements[0];
char* elements;
};
13 changes: 7 additions & 6 deletions XSharpRuntime/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,20 @@ bool printChar(char16_t character)
return 0;
}

bool printStr(char16_t* str)
bool printStr(xarray* char_array)
{
char16_t* str = (char16_t*)char_array->elements;
char buf[4];

while (*str) {
int len = UCS2toUTF8(*str, buf);
for (int i = 0; i < len; ++i) {
putchar(buf[i]);
for (int i = 0; i < char_array->length; ++i) {
int len = UCS2toUTF8(str[i], buf);
for (int j = 0; j < len; ++j) {
putchar(buf[j]);
}
str++;
}
return 0;
}

bool printI32(__int32_t x) { return printf("%d\n", x); }
bool printI64(__int64_t x) { return printf("%ld\n", x); }

Expand Down
3 changes: 2 additions & 1 deletion XSharpRuntime/io.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#pragma once
#include <stdio.h>
#include <stdbool.h>
#include "array.h"

// print scan related function
extern "C" bool printChar(char16_t character);
extern "C" bool printStr(char16_t* str);
extern "C" bool printStr(xarray* char_array);
extern "C" bool printI32(__int32_t x);
extern "C" bool printI64(__int64_t x);
extern "C" bool printFloat(float x);
Expand Down
16 changes: 2 additions & 14 deletions testcases/string.xsharp
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
class String{
char[] data;
i64 size;

void init(){
self.data = new char[](1024);
self.size = 1024;
return;
}
}

i32 main(){
char[] str = new char[](10);
str = "123\n\t123\n";
print(str);
char[] a = "123123";
print(a);
return 0;
}

0 comments on commit dff8655

Please sign in to comment.