Skip to content

Commit

Permalink
support multiple dimension array
Browse files Browse the repository at this point in the history
  • Loading branch information
rapiz1 committed Nov 4, 2021
1 parent c94d0de commit 488af3d
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 11 deletions.
4 changes: 2 additions & 2 deletions ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,10 @@ class Call : public Expr {

class Index : public Expr {
Expr* base;
Expr* idx;
std::vector<Expr*> idxs;

public:
Index(Expr* base, Expr* idx) : base(base), idx(idx){};
Index(Expr* base, std::vector<Expr*> idxs) : base(base), idxs(idxs){};
operator std::string() override { return "index " + std::string(*base); };
bool isLval() const override { return true; }

Expand Down
25 changes: 20 additions & 5 deletions parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -273,16 +273,30 @@ TypedVar Parser::typedVar() {
Token id = consume(IDENTIFIER, "Expect an identifer for variable");
Type type = {base};

if (match(1, LEFT_SQUARE)) {
while (match(1, LEFT_SQUARE)) {
// parse array type
advance();
auto num = consume(NUMBER, "Expect a number literal for array size");

int dim = 0;
std::stringstream ss(num.lexeme);
ss >> type.arraySize;
ss >> dim;
if (dim <= 0) {
std::cerr << "Invalid size of array at line " << num.line << std::endl;
exit(-1);
}

type.dims.push_back(dim);

type.isArray = true;
consume(RIGHT_SQUARE, "Expect `]` affter array size");
}

if (type.isArray) {
type.arraySize = 1;
for (auto x : type.dims) type.arraySize *= x;
}

return {type, id};
}

Expand Down Expand Up @@ -465,12 +479,13 @@ Expr* Parser::call() {

Expr* Parser::index() {
Expr* e = primary();
if (match(1, LEFT_SQUARE)) {
std::vector<Expr*> idxs;
while (match(1, LEFT_SQUARE)) {
advance();
auto i = expression();
e = new Index(e, i);
idxs.push_back(expression());
consume(RIGHT_SQUARE, "Expect `]` after indexing");
}
if (!idxs.empty()) e = new Index(e, idxs);
return e;
}

Expand Down
2 changes: 1 addition & 1 deletion parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Parser {
BlockStmt* forStmt(); // FOR '(' VAR_DECL EXPRESSION; EXPRESSION ')' STMT
WhileStmt* whileStmt(); // WHILE '(' EXPRESSION ')' STMT
ReturnStmt* returnStmt(); // RETURN EXPR;
TypedVar typedVar(); // (INT | DOUBLE | CHAR) '*'? ID ('['SIZE']')?
TypedVar typedVar(); // (INT | DOUBLE | CHAR) '*'? ID ('['SIZE']')*
VarDecl* varDecl(Type type, Token id); // TYPEDVAR
// (EQUAL EXPRESSION)? ;
FunDecl* funDecl(Type type,
Expand Down
34 changes: 34 additions & 0 deletions tests/types/2darray
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
int putchar(int c);
void printInt(int x) {
if (!x) {
putchar('0');
return;
}
int a[10];
int sz = 0;
while (x) {
a[sz] = x%10;
sz++;
x = x/10;
}
for (int i = sz-1; i >= 0; i--) {
putchar(a[i] + '0');
}
return;
}
int main() {
int a[3][3];
int c = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
a[i][j] = c++;
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printInt(a[i][j]);
putchar(' ');
}
putchar('\n');
}
return 0;
}
35 changes: 35 additions & 0 deletions tests/types/3darray
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
int putchar(int c);
void printInt(int x) {
if (!x) {
putchar('0');
return;
}
int a[10];
int sz = 0;
while (x) {
a[sz] = x%10;
sz++;
x = x/10;
}
for (int i = sz-1; i >= 0; i--) {
putchar(a[i] + '0');
}
return;
}
int main() {
int a[3][3][3];
int c = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
for (int k = 0; k < 3; k++) {
a[i][j][k] = c++;
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) {
printInt(a[i][j][k]);
putchar(' ');
}
putchar('\n');
}
return 0;
}
2 changes: 2 additions & 0 deletions type.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#pragma once
#include <string>
#include <vector>

#include "token.h"

struct Type {
enum class Base { VOID, INT, DOUBLE, CHAR, ARRAY, BOOL, FUNCTION } base;
int arraySize;
std::vector<int> dims;
bool isArray;
bool isPointer;
bool operator==(const Type& rhs) const {
Expand Down
19 changes: 16 additions & 3 deletions visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,28 @@ void CodeGenExprVisitor::visit(Variable* expr) {
addr = r.addr;
value = l.builder->CreateLoad(l.getType(r.type), r.addr, r.id.c_str());
}
type = r.type;
}
void CodeGenExprVisitor::visit(Index* expr) {
CodeGenExprVisitor ev(scope, l);
ev.visit(expr->base);
Type type = ev.getType();
CodeGenExprVisitor ev2(scope, l);
ev2.visit(expr->idx);
auto idx = ev2.getValue();
llvm::Value* offset =
llvm::Constant::getIntegerValue(l.getInt(), llvm::APInt(32, 0));
if (expr->idxs.size() != type.dims.size()) abortMsg("invalid array index");
for (size_t i = 0; i < expr->idxs.size(); i++) {
int factor = 1;
for (size_t j = i + 1; j < type.dims.size(); j++) factor *= type.dims[j];

ev2.visit(expr->idxs[i]);
auto factorValue =
llvm::Constant::getIntegerValue(l.getInt(), llvm::APInt(32, factor));
auto part_offset = l.builder->CreateMul(ev2.getValue(), factorValue);
offset = l.builder->CreateAdd(offset, part_offset);
}
auto base = ev.getValue();
auto ptr = l.builder->CreateGEP(base, idx);
auto ptr = l.builder->CreateGEP(base, offset);
value = l.builder->CreateLoad(ptr);
addr = static_cast<llvm::AllocaInst*>(ptr);
}
Expand Down
4 changes: 4 additions & 0 deletions visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class CodeGenExprVisitor : public ExprVisitor {
llvmWrapper l;
llvm::Value* value = nullptr;
llvm::AllocaInst* addr = nullptr;
Type type; // only used for array. other type information is passed by
// llvm::Value*

public:
CodeGenExprVisitor(Scope scope, llvmWrapper l) : scope(scope), l(l){};
Expand All @@ -86,6 +88,8 @@ class CodeGenExprVisitor : public ExprVisitor {
void visit(Call* expr) override;
void visit(Index* expr) override;

Type getType() { return type; }
void setType(Type t) { type = t; }
void setValue(llvm::Value* v) { value = v; }
void setAddr(llvm::AllocaInst* a) { addr = a; }
void setTuple(llvm::Value* v, llvm::AllocaInst* a = nullptr) {
Expand Down

0 comments on commit 488af3d

Please sign in to comment.