Skip to content

Commit

Permalink
Fix negative int out of range (#190)
Browse files Browse the repository at this point in the history
* Code optimization

* Fix bug and update test refs

* Add error check for function calls on variables
  • Loading branch information
marcauberer authored Aug 23, 2022
1 parent e471cb9 commit 2ac461d
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 238 deletions.
16 changes: 4 additions & 12 deletions media/test-project/os-test.spice
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ f<int> main() {
printf("Hello %s!", p1.getSecond());
}*/

/*import "std/type/int" as integer;
import "std/type/int" as integer;

const int vertexCount = 9;

f<int> minDistance(int[] dist, bool[] sptSet) {
int min = integer.MAX_VALUE;
int min = integer::MAX_VALUE;
int minIndex;

for int v = 0; v < vertexCount; v++ {
Expand All @@ -41,7 +41,7 @@ p dijkstra(int[vertexCount][vertexCount] graph, int src) {

// Fill with default values
for int i = 0; i < vertexCount; i++ {
dist[i] = integer.MAX_VALUE;
dist[i] = integer::MAX_VALUE;
sptSet[i] = false;
}

Expand All @@ -52,7 +52,7 @@ p dijkstra(int[vertexCount][vertexCount] graph, int src) {
int u = minDistance(dist, sptSet);
sptSet[u] = true;
for int v = 0; v < vertexCount; v++ {
if (!sptSet[v] && graph[u][v] != 0 && dist[u] != integer.MAX_VALUE &&
if (!sptSet[v] && graph[u][v] != 0 && dist[u] != integer::MAX_VALUE &&
dist[u] + graph[u][v] < dist[v]) {
dist[v] = dist[u] + graph[u][v];
}
Expand All @@ -78,12 +78,4 @@ f<int> main() {
printf("Computing shortest paths with Dijkstra's algorithm ...\n");
dijkstra(graph, 0);
printf("Done.\n");
}*/

import "std/data/pair" as pair;

f<int> main() {
pair::Pair<string, int> stringIntPair = pair::Pair<string, int>("Test", 1234);
printf("First: %s\n", stringIntPair.getFirst());
printf("Second: %d\n", stringIntPair.getSecond());
}
6 changes: 3 additions & 3 deletions src/Spice.g4
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ functionDef: specifierLst? F LESS dataType GREATER (IDENTIFIER DOT)? IDENTIFIER
procedureDef: specifierLst? P (IDENTIFIER DOT)? IDENTIFIER (LESS typeLst GREATER)? LPAREN paramLst? RPAREN LBRACE stmtLst RBRACE;
structDef: specifierLst? TYPE IDENTIFIER (LESS typeLst GREATER)? STRUCT LBRACE field* RBRACE;
genericTypeDef: specifierLst? TYPE IDENTIFIER typeAltsLst SEMICOLON;
globalVarDef: specifierLst? dataType IDENTIFIER (ASSIGN MINUS? value)? SEMICOLON;
globalVarDef: specifierLst? dataType IDENTIFIER (ASSIGN value)? SEMICOLON;
extDecl: EXT (LESS dataType GREATER)? IDENTIFIER LPAREN (typeLst ELLIPSIS?)? RPAREN DLL? SEMICOLON;
threadDef: THREAD LBRACE stmtLst RBRACE;
unsafeBlockDef: UNSAFE LBRACE stmtLst RBRACE;
Expand Down Expand Up @@ -171,15 +171,15 @@ SCOPE_ACCESS: '::';
ELLIPSIS: '...';

// Regex tokens
DOUBLE_LIT: [0-9]*[.][0-9]+;
DOUBLE_LIT: [-]?[0-9]*[.][0-9]+;
INT_LIT: NUM_LIT;
SHORT_LIT: NUM_LIT 's';
LONG_LIT: NUM_LIT 'l';
CHAR_LIT: '\'' (~['\\\r\n] | '\\' (. | EOF)) '\'';
STRING_LIT: '"' (~["\\\r\n] | '\\' (. | EOF))* '"';
IDENTIFIER: [a-zA-Z_][a-zA-Z0-9_]*;
fragment NUM_LIT: DEC_LIT | BIN_LIT | HEX_LIT | OCT_LIT;
fragment NUM_LIT: [-]?(DEC_LIT | BIN_LIT | HEX_LIT | OCT_LIT);
fragment DEC_LIT: ([0][dD])?[0-9]+;
fragment BIN_LIT: [0][bB][01]+;
fragment HEX_LIT: [0][xXhH][0-9a-fA-F]+;
Expand Down
11 changes: 4 additions & 7 deletions src/analyzer/AnalyzerVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,12 +696,6 @@ std::any AnalyzerVisitor::visitGlobalVarDef(GlobalVarDefNode *node) {
symbolTypeSpecifiers.setSigned(true);
} else if (specifier->type == SpecifierNode::TY_UNSIGNED) {
symbolTypeSpecifiers.setSigned(false);

// Check if there is a negative value attached. If yes, print a compiler warning
if (node->negative)
CompilerWarning(node->codeLoc, NEGATIVE_VALUE_TO_UNSIGNED_VAR,
"Please mind that assigning a negative value to an unsigned variable causes a wrap-around")
.print();
} else if (specifier->type == SpecifierNode::TY_PUBLIC) {
symbolTypeSpecifiers.setPublic(true);
} else {
Expand Down Expand Up @@ -1886,7 +1880,10 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) {

std::string tableName = symbolEntry->getType().is(TY_IMPORT) ? identifier : STRUCT_SCOPE_PREFIX + thisType.getName();
accessScope = accessScope->lookupTable(tableName);
assert(accessScope != nullptr);

if (!accessScope)
throw err->get(node->codeLoc, REFERENCED_UNDEFINED_FUNCTION, "Cannot call a function on '" + identifier + "'");

scopePath.pushFragment(identifier, accessScope);
}
assert(accessScope != nullptr);
Expand Down
1 change: 0 additions & 1 deletion src/ast/AstNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ class GlobalVarDefNode : public AstNode {

// Public members
std::string varName;
bool negative;
};

// ========================================================== ExtDeclNode ========================================================
Expand Down
41 changes: 18 additions & 23 deletions src/generator/GeneratorVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,9 +782,7 @@ std::any GeneratorVisitor::visitGlobalVarDef(GlobalVarDefNode *node) {
generateGlobalVarDebugInfo(global, globalVarEntry);

if (node->value()) { // Variable is initialized here
constNegate = node->negative;
visit(node->value());
constNegate = false;
global->setInitializer(currentConstValue);
} else {
llvm::Constant *defaultValue = getDefaultValueForSymbolType(globalVarEntry->getType());
Expand Down Expand Up @@ -2448,61 +2446,58 @@ std::any GeneratorVisitor::visitPrimitiveValue(PrimitiveValueNode *node) {
// Value is a double constant
if (node->type == PrimitiveValueNode::TYPE_DOUBLE) {
currentSymbolType = SymbolType(TY_DOUBLE);
double value = constNegate ? -node->data.doubleValue : node->data.doubleValue;
return static_cast<llvm::Constant *>(llvm::ConstantFP::get(*context, llvm::APFloat(value)));
llvm::Constant *value = llvm::ConstantFP::get(*context, llvm::APFloat(node->data.doubleValue));
return value;
}

// Value is an integer constant
if (node->type == PrimitiveValueNode::TYPE_INT) {
currentSymbolType = SymbolType(TY_INT);
int value = constNegate ? -node->data.intValue : node->data.intValue;
llvm::Type *intTy = builder->getInt32Ty();
llvm::Constant *constant =
currentConstSigned ? llvm::ConstantInt::getSigned(intTy, value) : llvm::ConstantInt::get(intTy, value);
return static_cast<llvm::Constant *>(constant);
llvm::Constant *constant = currentConstSigned ? llvm::ConstantInt::getSigned(intTy, node->data.intValue)
: llvm::ConstantInt::get(intTy, node->data.intValue);
return constant;
}

// Value is a short constant
if (node->type == PrimitiveValueNode::TYPE_SHORT) {
currentSymbolType = SymbolType(TY_SHORT);
int value = constNegate ? -node->data.shortValue : node->data.shortValue;
llvm::Type *shortTy = builder->getInt16Ty();
llvm::Constant *constant =
currentConstSigned ? llvm::ConstantInt::getSigned(shortTy, value) : llvm::ConstantInt::get(shortTy, value);
return static_cast<llvm::Constant *>(constant);
llvm::Constant *constant = currentConstSigned ? llvm::ConstantInt::getSigned(shortTy, node->data.shortValue)
: llvm::ConstantInt::get(shortTy, node->data.shortValue);
return constant;
}

// Value is a long constant
if (node->type == PrimitiveValueNode::TYPE_LONG) {
currentSymbolType = SymbolType(TY_LONG);
long long value = constNegate ? -node->data.longValue : node->data.longValue;
llvm::Type *longTy = builder->getInt64Ty();
llvm::Constant *constant =
currentConstSigned ? llvm::ConstantInt::getSigned(longTy, value) : llvm::ConstantInt::get(longTy, value);
return static_cast<llvm::Constant *>(constant);
llvm::Constant *constant = currentConstSigned ? llvm::ConstantInt::getSigned(longTy, node->data.longValue)
: llvm::ConstantInt::get(longTy, node->data.longValue);
return constant;
}

// Value is a char constant
if (node->type == PrimitiveValueNode::TYPE_CHAR) {
currentSymbolType = SymbolType(TY_CHAR);
char value = node->data.charValue;
llvm::Type *charTy = builder->getInt8Ty();
llvm::Constant *constant =
currentConstSigned ? llvm::ConstantInt::getSigned(charTy, value) : llvm::ConstantInt::get(charTy, value);
return static_cast<llvm::Constant *>(constant);
llvm::Constant *constant = currentConstSigned ? llvm::ConstantInt::getSigned(charTy, node->data.charValue)
: llvm::ConstantInt::get(charTy, node->data.charValue);
return constant;
}

// Value is a string constant
if (node->type == PrimitiveValueNode::TYPE_STRING) {
currentSymbolType = SymbolType(TY_STRING);
std::string value = node->data.stringValue;
return static_cast<llvm::Constant *>(builder->CreateGlobalStringPtr(value, "", 0, module.get()));
llvm::Constant *value = builder->CreateGlobalStringPtr(node->data.stringValue, "", 0, module.get());
return value;
}

// Value is a boolean constant
if (node->type == PrimitiveValueNode::TYPE_BOOL) {
currentSymbolType = SymbolType(TY_BOOL);
return static_cast<llvm::Constant *>(node->data.boolValue ? builder->getTrue() : builder->getFalse());
llvm::Constant *value = node->data.boolValue ? builder->getTrue() : builder->getFalse();
return value;
}

throw std::runtime_error("Internal compiler error: Primitive data type generator fall-through"); // GCOV_EXCL_LINE
Expand Down
1 change: 0 additions & 1 deletion src/generator/GeneratorVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ class GeneratorVisitor : public AstVisitor {
llvm::Instruction *allocaInsertInst = nullptr;
std::stack<llvm::BasicBlock *> breakBlocks;
std::stack<llvm::BasicBlock *> continueBlocks;
bool constNegate = false;
bool withinConstantArray = false;
bool allArgsHardcoded = true;
llvm::Constant *currentConstValue = nullptr;
Expand Down
3 changes: 0 additions & 3 deletions src/parser/AstBuilderVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,6 @@ std::any AstBuilderVisitor::visitGlobalVarDef(SpiceParser::GlobalVarDefContext *
// Extract function name
globalVarDefNode->varName = ctx->IDENTIFIER()->getText();

// Extract negative
globalVarDefNode->negative = ctx->MINUS();

for (const auto &subTree : ctx->children) {
antlr4::ParserRuleContext *rule;
if (rule = dynamic_cast<SpiceParser::SpecifierLstContext *>(subTree); rule != nullptr) // DeclSpecifiers
Expand Down
2 changes: 0 additions & 2 deletions src/util/CompilerWarning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ std::string CompilerWarning::getMessagePrefix(CompilerWarningType type) {
return "Array initialization item count exceeds arrays capacity";
case INDEX_EXCEEDS_ARRAY_SIZE:
return "Array index exceeds its size";
case NEGATIVE_VALUE_TO_UNSIGNED_VAR:
return "Negative value assigned to unsigned variable";
case UNINSTALL_FAILED:
return "Uninstall failed";
case VERIFIER_DISABLED:
Expand Down
1 change: 0 additions & 1 deletion src/util/CompilerWarning.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ enum CompilerWarningType {
UNUSED_VARIABLE,
ARRAY_TOO_MANY_VALUES,
INDEX_EXCEEDS_ARRAY_SIZE,
NEGATIVE_VALUE_TO_UNSIGNED_VAR,
UNINSTALL_FAILED,
VERIFIER_DISABLED
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Semantic error in ./test-files/analyzer/variables/error-global-var-different-type-assign/source.spice:1:33: Wrong data type for operator: Cannot apply the assign operator on different data types. You provided short and int
Semantic error in ./test-files/analyzer/variables/error-global-var-different-type-assign/source.spice:1:32: Wrong data type for operator: Cannot apply the assign operator on different data types. You provided short and int
105 changes: 49 additions & 56 deletions test/test-files/generator/builtins/success-sizeof/ir-code.ll
Original file line number Diff line number Diff line change
Expand Up @@ -21,71 +21,64 @@ define i32 @main() {
entry.l7:
%result = alloca i32, align 4
store i32 0, ptr %result, align 4
%0 = alloca double, align 8
store double 0x40335992641B328B, ptr %0, align 8
%1 = load double, ptr %0, align 8
%2 = fmul double %1, -1.000000e+00
%3 = alloca double, align 8
store double %2, ptr %3, align 8
%4 = load double, ptr %3, align 8
%5 = alloca i32, align 4
store i32 64, ptr %5, align 4
%6 = load i32, ptr %5, align 4
%7 = call i32 (ptr, ...) @printf(ptr @0, i32 %6)
%8 = alloca i32, align 4
store i32 32, ptr %8, align 4
%9 = load i32, ptr %8, align 4
%10 = call i32 (ptr, ...) @printf(ptr @1, i32 %9)
%11 = alloca i32, align 4
store i32 16, ptr %11, align 4
%12 = load i32, ptr %11, align 4
%13 = call i32 (ptr, ...) @printf(ptr @2, i32 %12)
%0 = alloca i32, align 4
store i32 64, ptr %0, align 4
%1 = load i32, ptr %0, align 4
%2 = call i32 (ptr, ...) @printf(ptr @0, i32 %1)
%3 = alloca i32, align 4
store i32 32, ptr %3, align 4
%4 = load i32, ptr %3, align 4
%5 = call i32 (ptr, ...) @printf(ptr @1, i32 %4)
%6 = alloca i32, align 4
store i32 16, ptr %6, align 4
%7 = load i32, ptr %6, align 4
%8 = call i32 (ptr, ...) @printf(ptr @2, i32 %7)
%9 = alloca i32, align 4
store i32 64, ptr %9, align 4
%10 = load i32, ptr %9, align 4
%11 = call i32 (ptr, ...) @printf(ptr @3, i32 %10)
%12 = alloca i8, align 1
store i8 13, ptr %12, align 1
%13 = load i8, ptr %12, align 1
%14 = alloca i32, align 4
store i32 64, ptr %14, align 4
store i32 8, ptr %14, align 4
%15 = load i32, ptr %14, align 4
%16 = call i32 (ptr, ...) @printf(ptr @3, i32 %15)
%16 = call i32 (ptr, ...) @printf(ptr @4, i32 %15)
%17 = alloca i8, align 1
store i8 13, ptr %17, align 1
store i8 65, ptr %17, align 1
%18 = load i8, ptr %17, align 1
%19 = alloca i32, align 4
store i32 8, ptr %19, align 4
%20 = load i32, ptr %19, align 4
%21 = call i32 (ptr, ...) @printf(ptr @4, i32 %20)
%22 = alloca i8, align 1
store i8 65, ptr %22, align 1
%23 = load i8, ptr %22, align 1
%24 = alloca i32, align 4
store i32 8, ptr %24, align 4
%25 = load i32, ptr %24, align 4
%26 = call i32 (ptr, ...) @printf(ptr @5, i32 %25)
%27 = alloca i32, align 4
store i32 64, ptr %27, align 4
%28 = load i32, ptr %27, align 4
%29 = call i32 (ptr, ...) @printf(ptr @6, i32 %28)
%30 = alloca i32, align 4
store i32 1, ptr %30, align 4
%31 = load i32, ptr %30, align 4
%32 = call i32 (ptr, ...) @printf(ptr @8, i32 %31)
%33 = load [7 x i32], ptr @anonymous.0, align 4
%34 = alloca i32, align 4
store i32 224, ptr %34, align 4
%35 = load i32, ptr %34, align 4
%36 = call i32 (ptr, ...) @printf(ptr @9, i32 %35)
%21 = call i32 (ptr, ...) @printf(ptr @5, i32 %20)
%22 = alloca i32, align 4
store i32 64, ptr %22, align 4
%23 = load i32, ptr %22, align 4
%24 = call i32 (ptr, ...) @printf(ptr @6, i32 %23)
%25 = alloca i32, align 4
store i32 1, ptr %25, align 4
%26 = load i32, ptr %25, align 4
%27 = call i32 (ptr, ...) @printf(ptr @8, i32 %26)
%28 = load [7 x i32], ptr @anonymous.0, align 4
%29 = alloca i32, align 4
store i32 224, ptr %29, align 4
%30 = load i32, ptr %29, align 4
%31 = call i32 (ptr, ...) @printf(ptr @9, i32 %30)
%intVariable = alloca i32, align 4
store i32 123, ptr %intVariable, align 4
%37 = alloca ptr, align 8
store ptr %intVariable, ptr %37, align 8
%38 = load ptr, ptr %37, align 8
%39 = alloca i32, align 4
store i32 64, ptr %39, align 4
%40 = load i32, ptr %39, align 4
%41 = call i32 (ptr, ...) @printf(ptr @10, i32 %40)
%42 = alloca i32, align 4
store i32 128, ptr %42, align 4
%43 = load i32, ptr %42, align 4
%44 = call i32 (ptr, ...) @printf(ptr @11, i32 %43)
%45 = load i32, ptr %result, align 4
ret i32 %45
%32 = alloca ptr, align 8
store ptr %intVariable, ptr %32, align 8
%33 = load ptr, ptr %32, align 8
%34 = alloca i32, align 4
store i32 64, ptr %34, align 4
%35 = load i32, ptr %34, align 4
%36 = call i32 (ptr, ...) @printf(ptr @10, i32 %35)
%37 = alloca i32, align 4
store i32 128, ptr %37, align 4
%38 = load i32, ptr %37, align 4
%39 = call i32 (ptr, ...) @printf(ptr @11, i32 %38)
%40 = load i32, ptr %result, align 4
ret i32 %40
}

declare i32 @printf(ptr, ...)
Loading

0 comments on commit 2ac461d

Please sign in to comment.