Skip to content

Commit

Permalink
Simplify code (#709)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer authored Jan 13, 2025
1 parent cf24ddf commit 5a60077
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .run/spice run.run.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="spice run" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -O2 -d ../../media/test-project/test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spice" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spice">
<configuration default="false" name="spice run" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -O0 -d -ir ../../media/test-project/test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="spice" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="spice">
<envs>
<env name="LLVM_ADDITIONAL_FLAGS" value="-lole32 -lws2_32" />
<env name="LLVM_BUILD_INCLUDE_DIR" value="$PROJECT_DIR$/../llvm-project-latest/build/include" />
Expand Down
8 changes: 3 additions & 5 deletions src/irgenerator/GenStatements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,9 @@ std::any IRGenerator::visitReturnStmt(const ReturnStmtNode *node) {

llvm::Value *returnValue = nullptr;
if (node->hasReturnValue) { // Return value is attached to the return statement
if (node->getEvaluatedSymbolType(manIdx).isRef())
returnValue = resolveAddress(node->assignExpr);
else
returnValue = resolveValue(node->assignExpr);
} else { // Try to load return variable value
const AssignExprNode* returnExpr = node->assignExpr;
returnValue = node->getEvaluatedSymbolType(manIdx).isRef() ? resolveAddress(returnExpr) : resolveValue(returnExpr);
} else { // Try to load result variable value
const SymbolTableEntry *resultEntry = currentScope->lookup(RETURN_VARIABLE_NAME);
if (resultEntry != nullptr) {
llvm::Type *resultSTy = resultEntry->getQualType().toLLVMType(sourceFile);
Expand Down
30 changes: 27 additions & 3 deletions src/symboltablebuilder/QualType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,25 @@ bool QualType::isBase(SuperType superType) const { return type->isBase(superType

/**
* Check if the underlying type is a primitive type
* Note: enum types are mapped to int, so they are also count as primitive types.
*
* @return Primitive or not
*/
bool QualType::isPrimitive() const { return type->isPrimitive(); }

/**
* Check if the underlying type is an extended primitive type
* The definition of extended primitive types contains all primitive types plus the following:
* - structs
* - interfaces
* - functions/procedures
*
* @return Extended primitive or not
*/
bool QualType::isExtendedPrimitive() const {
return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE});
}

/**
* Check if the underlying type is a pointer
*
Expand Down Expand Up @@ -192,7 +206,7 @@ bool QualType::isArrayOf(SuperType superType) const { return isArray() && getCon
*
* @return Const reference or not
*/
bool QualType::isConstRef() const { return isConst() && isRef(); }
bool QualType::isConstRef() const { return specifiers.isConst && isRef(); }

/**
* Check if the current type is an iterator
Expand Down Expand Up @@ -679,11 +693,21 @@ QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType
}

/**
* Check if the current type is marked const
* Check if the current type is const
*
* Examples for const types:
* - const int
* - const TestStruct
* - const string
*
* Examples for non-const types:
* - double (reason: not marked const)
* - const int* (reason: pointer to const int is not const itself)
* - const TestStruct& (reason: reference to const TestStruct is not const itself)
*
* @return Is const or not
*/
bool QualType::isConst() const { return specifiers.isConst; }
bool QualType::isConst() const { return isExtendedPrimitive() && specifiers.isConst; }

/**
* Check if the current type is marked signed
Expand Down
1 change: 1 addition & 0 deletions src/symboltablebuilder/QualType.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class QualType {
[[nodiscard]] bool isOneOf(const std::initializer_list<SuperType> &superTypes) const;
[[nodiscard]] bool isBase(SuperType superType) const;
[[nodiscard]] bool isPrimitive() const;
[[nodiscard]] bool isExtendedPrimitive() const;
[[nodiscard]] bool isPtr() const;
[[nodiscard]] bool isPtrTo(SuperType superType) const;
[[nodiscard]] bool isRef() const;
Expand Down
10 changes: 6 additions & 4 deletions src/typechecker/OpRuleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ QualType OpRuleManager::getAssignResultType(const ASTNode *node, const ExprResul
// If this is const ref, remove both: the reference and the constness
const QualType rhsModified = rhsType.getContained().toNonConst();
if (lhsType.matches(rhsModified, false, !lhsType.isRef(), true)) {
// In case of a return expression, we perform temp stealing
if (rhsModified.is(TY_STRUCT) && !rhs.isTemporary() && !isReturn)
// Check if we support nrvo. If yes, skip the implicit copy ctor call
const bool supportsNRVO = isReturn && !rhs.isTemporary();
if (rhsModified.is(TY_STRUCT) && rhs.entry != nullptr && !supportsNRVO)
typeChecker->implicitlyCallStructCopyCtor(rhs.entry, rhs.entry->declNode);
return lhsType;
}
Expand All @@ -50,8 +51,9 @@ QualType OpRuleManager::getAssignResultType(const ASTNode *node, const ExprResul
return rhsType;
// Allow struct of the same type straight away
if (lhsType.is(TY_STRUCT) && lhsType.matches(rhsType, false, true, true)) {
// In case of a return expression, we perform temp stealing
if (!rhs.isTemporary() && !isReturn)
// Check if we support nrvo. If yes, skip the implicit copy ctor call
const bool supportsNRVO = isReturn && !rhs.isTemporary();
if (rhs.entry != nullptr && !supportsNRVO)
typeChecker->implicitlyCallStructCopyCtor(rhs.entry, rhs.entry->declNode);
return rhsType;
}
Expand Down
6 changes: 3 additions & 3 deletions src/typechecker/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ std::any TypeChecker::visitReturnStmt(ReturnStmtNode *node) {
const ExprResult returnResult = {returnType, returnVar};
(void)opRuleManager.getAssignResultType(node->assignExpr, returnResult, rhs, false, true, ERROR_MSG_RETURN);

// Manage dtor call
// Check if the dtor call on the return value can be skipped
if (rhs.entry != nullptr) {
if (rhs.entry->anonymous) {
// If there is an anonymous entry attached (e.g. for struct instantiation), delete it
Expand Down Expand Up @@ -1529,9 +1529,9 @@ std::any TypeChecker::visitAtomicExpr(AtomicExprNode *node) {
if (varType.is(TY_INVALID))
SOFT_ERROR_ER(node, USED_BEFORE_DECLARED, "Symbol '" + varEntry->name + "' was used before declared.")

// The base type should be a primitive, struct, interface, function or procedure
// The base type should be an extended primitive
const QualType baseType = varType.getBase();
if (!baseType.isPrimitive() && !baseType.isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE, TY_DYN}))
if (!baseType.isExtendedPrimitive() && !baseType.is(TY_DYN))
SOFT_ERROR_ER(node, INVALID_SYMBOL_ACCESS, "A symbol of type " + varType.getName(false) + " cannot be accessed here")

// Check if is an imported variable
Expand Down

0 comments on commit 5a60077

Please sign in to comment.