diff --git a/effekt/jvm/src/main/scala/effekt/Runner.scala b/effekt/jvm/src/main/scala/effekt/Runner.scala index 056b86b39..b9f34f253 100644 --- a/effekt/jvm/src/main/scala/effekt/Runner.scala +++ b/effekt/jvm/src/main/scala/effekt/Runner.scala @@ -287,9 +287,15 @@ object LLVMRunner extends Runner[String] { def libuvArgs(using C: Context): Seq[String] = val OS = System.getProperty("os.name").toLowerCase + + // only relevant for macOS + val arch: String = System.getProperty("os.arch") + assert(!OS.contains("mac") || List("aarch64", "x86_64").contains(arch), "If you have a macbook -> It should have either an aarch64 or x86_64 architecture.") + val libraries = C.config.clangLibraries.toOption.map(file).orElse { OS match { - case os if os.contains("mac") => Some(file("/opt/homebrew/lib")) + case os if os.contains("mac") && arch.equals("aarch64") => Some(file("/opt/homebrew/lib")) + case os if os.contains("mac") => Some(file("/usr/local/lib")) case os if os.contains("win") => None case os if os.contains("linux") => Some(file("/usr/local/lib")) case os => None @@ -297,7 +303,8 @@ object LLVMRunner extends Runner[String] { } val includes = C.config.clangIncludes.toOption.map(file).orElse { OS match { - case os if os.contains("mac") => Some(file("/opt/homebrew/include")) + case os if os.contains("mac") && arch.equals("aarch64") => Some(file("/opt/homebrew/include")) + case os if os.contains("mac") => Some(file("/usr/local/include")) case os if os.contains("win") => None case os if os.contains("linux") => Some(file("/usr/local/include")) case os => None diff --git a/effekt/jvm/src/test/scala/effekt/FlatTests.scala b/effekt/jvm/src/test/scala/effekt/FlatTests.scala new file mode 100644 index 000000000..c0c0f6e5c --- /dev/null +++ b/effekt/jvm/src/test/scala/effekt/FlatTests.scala @@ -0,0 +1,24 @@ +package effekt + +import sbt.io.* +import sbt.io.syntax.* + +import java.io.File +import scala.language.implicitConversions +import scala.sys.process.Process + +// df: My own test class to run my requested tests automatically +class FlatTests extends EffektTests { + + def backendName = "llvm" + + override def valgrind = false // works on linux only + + override lazy val positives: Set[File] = Set( + examplesDir / "flat" / "optimized" + ) + + override lazy val withoutOptimizations: Set[File] = Set( + examplesDir / "flat" / "nooptimized", + ) +} diff --git a/effekt/jvm/src/test/scala/effekt/LLVMTests.scala b/effekt/jvm/src/test/scala/effekt/LLVMTests.scala index 85d9a418a..89b9c6f34 100644 --- a/effekt/jvm/src/test/scala/effekt/LLVMTests.scala +++ b/effekt/jvm/src/test/scala/effekt/LLVMTests.scala @@ -12,7 +12,7 @@ class LLVMTests extends EffektTests { override def valgrind = sys.env.get("EFFEKT_VALGRIND").nonEmpty override def debug = sys.env.get("EFFEKT_DEBUG").nonEmpty - + override lazy val positives: Set[File] = Set( examplesDir / "llvm", examplesDir / "pos", diff --git a/effekt/shared/src/main/scala/effekt/generator/llvm/Transformer.scala b/effekt/shared/src/main/scala/effekt/generator/llvm/Transformer.scala index 87755c407..c8bf5d3fe 100644 --- a/effekt/shared/src/main/scala/effekt/generator/llvm/Transformer.scala +++ b/effekt/shared/src/main/scala/effekt/generator/llvm/Transformer.scala @@ -2,17 +2,22 @@ package effekt package generator package llvm +import effekt.generator.llvm.Type as LLVMType +import effekt.generator.llvm.Instruction.{Call, Load} import effekt.machine +import effekt.machine.{Environment, Variable} +import effekt.machine.analysis.* import effekt.util.intercalate import effekt.util.messages.ErrorReporter -import effekt.machine.analysis.* import scala.annotation.tailrec import scala.collection.mutable +import scala.collection.mutable.ListBuffer object Transformer { val llvmFeatureFlags: List[String] = List("llvm") + val slotSize: Int = 64 // the size of a heap slot in bytes def transform(program: machine.Program)(using ErrorReporter): List[Definition] = program match { case machine.Program(declarations, definitions, entry) => @@ -20,11 +25,14 @@ object Transformer { given MC: ModuleContext = ModuleContext(); definitions.foreach(transform); - val globals = MC.definitions; MC.definitions = null; + val globals = MC.definitions; + MC.definitions = null; val entryInstructions = List( Call("stack", Ccc(), stackType, withEmptyStack, List()), - Call("_", Tailcc(false), VoidType(), transform(entry), List(LocalReference(stackType, "stack")))) + Call("", Ccc(), VoidType(), initializeMemory, List()), + Call("_", Tailcc(false), VoidType(), transform(entry), List(LocalReference(stackType, "stack"))), + ) val entryBlock = BasicBlock("entry", entryInstructions, RetVoid()) val entryFunction = Function(External(), Ccc(), VoidType(), "effektMain", List(), List(entryBlock)) @@ -33,7 +41,9 @@ object Transformer { // context getters private def MC(using MC: ModuleContext): ModuleContext = MC + private def FC(using FC: FunctionContext): FunctionContext = FC + private def BC(using BC: BlockContext): BlockContext = BC def transform(declaration: machine.Declaration)(using ErrorReporter): Definition = @@ -57,26 +67,26 @@ object Transformer { """call void @hole() |unreachable |""".stripMargin - } + } def transform(template: Template[machine.Variable]): String = "; variable\n " ++ intercalate(template.strings, template.args.map { case machine.Variable(name, tpe) => PrettyPrinter.localName(name) }).mkString def transform(definition: machine.Definition)(using ModuleContext): Unit = definition match { - case machine.Definition(machine.Label(name, environment), body) => - val parameters = environment.map { case machine.Variable(name, tpe) => Parameter(transform(tpe), name) } - defineLabel(name, parameters) { - emit(Comment(s"definition $name, environment length ${environment.length}")) - eraseValues(environment, freeVariables(body)) - transform(body) - } + case machine.Definition(machine.Label(name, environment), body) => + val parameters = environment.map { case machine.Variable(name, tpe) => Parameter(transform(tpe), name) } + defineLabel(name, parameters) { + emit(Comment(s"definition $name, environment length ${environment.length}")) + eraseValues(environment, freeVariables(body)) + transform(body) + } } def transform(statement: machine.Statement)(using ModuleContext, FunctionContext, BlockContext): Terminator = statement match { - case machine.Jump(label, arguments) => + case machine.Jump(label, arguments) => emit(Comment(s"jump ${label.name}")) shareValues(arguments, Set()) emit(callLabel(transform(label), arguments.map(transform))) @@ -103,6 +113,7 @@ object Transformer { emit(ExtractValue(objectName, transform(value), 1)) val stack = getStack() + def labelClause(clause: machine.Clause, isDefault: Boolean): String = { implicit val BC = BlockContext() BC.stack = stack @@ -179,7 +190,7 @@ object Transformer { emit(callLabel(LocalReference(methodType, functionName), LocalReference(objectType, objectName) +: arguments)) RetVoid() - case machine.Var(ref @ machine.Variable(name, machine.Type.Reference(tpe)), init, retType, rest) => + case machine.Var(ref@machine.Variable(name, machine.Type.Reference(tpe)), init, retType, rest) => val environment = List(init) val returnAddressName = freshName("returnAddress") val returnType = transform(retType) @@ -354,7 +365,7 @@ object Transformer { eraseValues(List(v), freeVariables(rest)); transform(rest) - case machine.ForeignCall(variable @ machine.Variable(resultName, resultType), foreign, values, rest) => + case machine.ForeignCall(variable@machine.Variable(resultName, resultType), foreign, values, rest) => emit(Comment(s"foreignCall $resultName : $resultType, foreign $foreign, ${values.length} values")) shareValues(values, freeVariables(rest)); emit(Call(resultName, Ccc(), transform(resultType), ConstantGlobal(foreign), values.map(transform))); @@ -387,17 +398,17 @@ object Transformer { } transform(rest) - case machine.Statement.Hole(span) => - val posfmt = span.range.from.format - emit(Comment(s"Hole @ $posfmt")) + case machine.Statement.Hole(span) => + val posfmt = span.range.from.format + emit(Comment(s"Hole @ $posfmt")) - // Reused from LiteralUTF8String - val utf8 = (posfmt + "\u0000").getBytes("UTF-8") // null-terminated - val litName = freshName("hole_pos") - emit(GlobalConstant(s"$litName.lit", ConstantArray(IntegerType8(), utf8.map { b => ConstantInteger8(b) }.toList))) + // Reused from LiteralUTF8String + val utf8 = (posfmt + "\u0000").getBytes("UTF-8") // null-terminated + val litName = freshName("hole_pos") + emit(GlobalConstant(s"$litName.lit", ConstantArray(IntegerType8(), utf8.map { b => ConstantInteger8(b) }.toList))) - emit(Call("_", Ccc(), VoidType(), ConstantGlobal("hole"), List(ConstantGlobal(s"$litName.lit")))) - RetVoid() + emit(Call("_", Ccc(), VoidType(), ConstantGlobal("hole"), List(ConstantGlobal(s"$litName.lit")))) + RetVoid() } def transform(label: machine.Label): ConstantGlobal = @@ -425,15 +436,17 @@ object Transformer { val resumptionType = NamedType("Resumption"); val promptType = NamedType("Prompt"); val referenceType = NamedType("Reference"); + val headerType = NamedType("Header"); + val referenceCountType = NamedType("ReferenceCount"); def transform(tpe: machine.Type): Type = tpe match { - case machine.Positive() => positiveType - case machine.Negative() => negativeType - case machine.Type.Prompt() => promptType - case machine.Type.Stack() => resumptionType - case machine.Type.Int() => IntegerType64() - case machine.Type.Byte() => IntegerType8() - case machine.Type.Double() => DoubleType() + case machine.Positive() => positiveType + case machine.Negative() => negativeType + case machine.Type.Prompt() => promptType + case machine.Type.Stack() => resumptionType + case machine.Type.Int() => IntegerType64() + case machine.Type.Byte() => IntegerType8() + case machine.Type.Double() => DoubleType() case machine.Type.Reference(tpe) => referenceType } @@ -442,13 +455,13 @@ object Transformer { def typeSize(tpe: machine.Type): Int = tpe match { - case machine.Positive() => 16 - case machine.Negative() => 16 - case machine.Type.Prompt() => 8 // TODO Make fat? - case machine.Type.Stack() => 8 // TODO Make fat? - case machine.Type.Int() => 8 // TODO Make fat? - case machine.Type.Byte() => 1 - case machine.Type.Double() => 8 // TODO Make fat? + case machine.Positive() => 16 + case machine.Negative() => 16 + case machine.Type.Prompt() => 8 // TODO Make fat? + case machine.Type.Stack() => 8 // TODO Make fat? + case machine.Type.Int() => 8 // TODO Make fat? + case machine.Type.Byte() => 1 + case machine.Type.Double() => 8 // TODO Make fat? case machine.Type.Reference(_) => 16 } @@ -458,8 +471,10 @@ object Transformer { val terminator = prog; - val basicBlocks = FC.basicBlocks; FC.basicBlocks = null; - val instructions = BC.instructions; BC.instructions = null; + val basicBlocks = FC.basicBlocks; + FC.basicBlocks = null; + val instructions = BC.instructions; + BC.instructions = null; val entryBlock = BasicBlock("entry", instructions, terminator); val function = Function(Private(), Ccc(), VoidType(), name, parameters, entryBlock :: basicBlocks); @@ -473,8 +488,10 @@ object Transformer { val terminator = prog; - val basicBlocks = FC.basicBlocks; FC.basicBlocks = null; - val instructions = BC.instructions; BC.instructions = null; + val basicBlocks = FC.basicBlocks; + FC.basicBlocks = null; + val instructions = BC.instructions; + BC.instructions = null; val entryBlock = BasicBlock("entry", instructions, terminator); val function = Function(Private(), Tailcc(true), VoidType(), name, parameters :+ Parameter(stackType, "stack"), entryBlock :: basicBlocks); @@ -507,24 +524,17 @@ object Transformer { } def getEraser(environment: machine.Environment, kind: EraserKind)(using C: ModuleContext): Operand = { - val types = environment.map{ _.tpe }; - val freshEnvironment = environment.map{ + val types = environment.map { + _.tpe + }; + val freshEnvironment = environment.map { case machine.Variable(name, tpe) => machine.Variable(freshName(name), tpe) }; C.erasers.getOrElseUpdate((types, kind), { kind match { case ObjectEraser => - val eraser = ConstantGlobal(freshName("eraser")); - defineFunction(eraser.name, List(Parameter(environmentType, "environment"))) { - emit(Comment(s"${kind} eraser, ${freshEnvironment.length} free variables")) - - // TODO avoid unnecessary loads - loadEnvironmentAt(LocalReference(environmentType, "environment"), freshEnvironment, Object); - eraseValues(freshEnvironment, Set()); - RetVoid() - }; - eraser + createEraserForNormalObjects(freshEnvironment) case StackEraser | StackFrameEraser => val eraser = ConstantGlobal(freshName("eraser")); defineFunction(eraser.name, List(Parameter(stackPointerType, "stackPointer"))) { @@ -545,8 +555,10 @@ object Transformer { } def getSharer(environment: machine.Environment, kind: SharerKind)(using C: ModuleContext): Operand = { - val types = environment.map{ _.tpe }; - val freshEnvironment = environment.map{ + val types = environment.map { + _.tpe + }; + val freshEnvironment = environment.map { case machine.Variable(name, tpe) => machine.Variable(freshName(name), tpe) }; @@ -569,20 +581,16 @@ object Transformer { }) } + /** + * Produces an Object. It is always ${slotSize} bytes long + */ def produceObject(role: String, environment: machine.Environment, freeInBody: Set[machine.Variable])(using ModuleContext, FunctionContext, BlockContext): Operand = { if (environment.isEmpty) { ConstantNull(objectType) + } else if (fitsInOneSavingSlot(environment)) { + produceSingleObject(role, environment, freeInBody) } else { - val objectReference = LocalReference(objectType, freshName(role)); - val environmentReference = LocalReference(environmentType, freshName("environment")); - val size = ConstantInt(environmentSize(environment)); - val eraser = getEraser(environment, ObjectEraser) - - emit(Call(objectReference.name, Ccc(), objectType, newObject, List(eraser, size))); - emit(Call(environmentReference.name, Ccc(), environmentType, objectEnvironment, List(objectReference))); - shareValues(environment, freeInBody); - storeEnvironment(environmentReference, environment, Object); - objectReference + produceShardedObject(role, environment, freeInBody) } } @@ -651,13 +659,45 @@ object Transformer { } } - def loadEnvironmentAt(pointer: Operand, environment: machine.Environment, alias: AliasInfo)(using ModuleContext, FunctionContext, BlockContext): Unit = { - val `type` = environmentType(environment) - environment.zipWithIndex.foreach { - case (machine.Variable(name, tpe), i) => - val field = LocalReference(PointerType(), freshName(name + "_pointer")); - emit(GetElementPtr(field.name, `type`, pointer, List(0, i))); - emit(Load(name, transform(tpe), field, alias)) + def loadEnvironmentAt(elementPointer: Operand, environment: machine.Environment, alias: AliasInfo)(using ModuleContext, FunctionContext, BlockContext): Unit = { + alias match { + // if we have a sharded object + case Object if !fitsInOneSavingSlot(environment) => + // Follow chained ${slotSize}-byte blocks created in produceObject + val chunkedEnvironments = splitEnvironment(environment) + var currentEnvironmentPtr: Operand = elementPointer + + // here we loop over all environments *in* order + chunkedEnvironments.zipWithIndex.foreach { case (chunk, idx) => + val isLast = idx == chunkedEnvironments.length - 1 + if (isLast) { + val tpe = environmentType(chunk) + loadAllVariables(currentEnvironmentPtr, chunk, alias, tpe) + } else { + // Here we do the same as for the normal slot plus some extra stuff + + // For non-last chunkedEnvironments, layout is chunk ++ [Pos link] + val tpe = StructureType(chunk.map { case machine.Variable(_, t) => transform(t) } :+ positiveType) // the same as for the normal case + positive Type for the link + loadAllVariables(currentEnvironmentPtr, chunk, alias, tpe) + + // Follow link to next block. The Link pointer is the last element of the chunk + val linkPtr = LocalReference(PointerType(), freshName("link_pointer")) + emit(GetElementPtr(linkPtr.name, tpe, currentEnvironmentPtr, List(0, chunk.length))) + + val linkVal = LocalReference(positiveType, freshName("link")) + emit(Load(linkVal.name, positiveType, linkPtr, alias)) + + val nextObj = LocalReference(objectType, freshName("next_object")) + emit(ExtractValue(nextObj.name, linkVal, 1)) + + val nextEnv = LocalReference(environmentType, freshName("environment")) + emit(Call(nextEnv.name, Ccc(), environmentType, objectEnvironment, List(nextObj))) + currentEnvironmentPtr = nextEnv + } + } + case _: AliasInfo => + val tpe = environmentType(environment) + loadAllVariables(elementPointer, environment, alias, tpe) } } @@ -667,15 +707,15 @@ object Transformer { values match { case Nil => () case value :: values => - if values.contains(value) then { - shareValue(value); - loop(values) - } else if freeInBody.contains(value) then { - shareValue(value); - loop(values) - } else { - loop(values) - } + if values.contains(value) then { + shareValue(value); + loop(values) + } else if freeInBody.contains(value) then { + shareValue(value); + loop(values) + } else { + loop(values) + } } }; loop(values) @@ -688,17 +728,17 @@ object Transformer { def shareValue(value: machine.Variable)(using FunctionContext, BlockContext): Unit = { Option(value.tpe).collect { - case machine.Positive() => Call("_", Ccc(), VoidType(), sharePositive, List(transform(value))) - case machine.Negative() => Call("_", Ccc(), VoidType(), shareNegative, List(transform(value))) - case machine.Type.Stack() => Call("_", Ccc(), VoidType(), shareResumption, List(transform(value))) + case machine.Positive() => Call("_", Ccc(), VoidType(), sharePositive, List(transform(value))) + case machine.Negative() => Call("_", Ccc(), VoidType(), shareNegative, List(transform(value))) + case machine.Type.Stack() => Call("_", Ccc(), VoidType(), shareResumption, List(transform(value))) }.map(emit) } def eraseValue(value: machine.Variable)(using FunctionContext, BlockContext): Unit = { Option(value.tpe).collect { - case machine.Positive() => Call("_", Ccc(), VoidType(), erasePositive, List(transform(value))) - case machine.Negative() => Call("_", Ccc(), VoidType(), eraseNegative, List(transform(value))) - case machine.Type.Stack() => Call("_", Ccc(), VoidType(), eraseResumption, List(transform(value))) + case machine.Positive() => Call("_", Ccc(), VoidType(), erasePositive, List(transform(value))) + case machine.Negative() => Call("_", Ccc(), VoidType(), eraseNegative, List(transform(value))) + case machine.Type.Stack() => Call("_", Ccc(), VoidType(), eraseResumption, List(transform(value))) }.map(emit) } @@ -715,6 +755,7 @@ object Transformer { emit(Load(returnAddressName, returnAddressType, returnAddressPointer, StackPointer)); } + val initializeMemory = ConstantGlobal("initializeMemory"); val newObject = ConstantGlobal("newObject"); val objectEnvironment = ConstantGlobal("objectEnvironment"); @@ -783,7 +824,7 @@ object Transformer { def setStack(stack: Operand)(using C: BlockContext) = C.stack = stack; - val escapeSeqs: Map[Char, String] = Map('\'' -> raw"'", '\"' -> raw"\"", '\\' -> raw"\\", '\n' -> raw"\n", '\t' -> raw"\t", '\r' -> raw"\r") + val escapeSeqs: Map[Char, String] = Map('\'' -> raw"'", '\"' -> raw"\"", '\\' -> raw" \\ ", '\n' -> raw" \ n", '\t' -> raw" \ t", '\r' -> raw" \ r") def escape(scalaString: String): String = scalaString.foldLeft(StringBuilder()) { (acc, c) => @@ -792,4 +833,205 @@ object Transformer { case None => acc += c } }.toString() + + /** + * if we can fit our object in one single saving block -> Easiest case + * Else we have to split our environment into multiple saving slots and reference in a linked list fashion + */ + private def fitsInOneSavingSlot(environment: machine.Environment): Boolean = { + environmentSize(environment) > 0 && environmentSize(environment) <= 48 + } + + /** + * Splits the environment into multiple environment such that you can store one object in multiple saving slots. + * Is required to do fixed-sized-allocation. + */ + private def splitEnvironment(environment: machine.Environment): List[machine.Environment] = { + val headerSize = 16 // we use 16 byte for the last saving block only, the others are 32 bytes + val linkSize = 16 // how much bytes we need to store the link to the next block (%Pos object) + + // How much bytes do we need to reserve to save a slot? + // The last block only needs 16 bytes, because here we only need to store the header. + // For all other blocks we need 32 bytes, because we need to store the header and the link to the next block. + var reservedSpaceForSlot = headerSize + + var currentEnvironment = List[machine.Variable]() + var result = List[machine.Environment]() + var isLast = true + for (variable <- environment.reverse) { + val variableSize = typeSize(variable.tpe) + + if (reservedSpaceForSlot + (environmentSize(currentEnvironment) + variableSize) <= slotSize) { + currentEnvironment = currentEnvironment :+ variable + } + else { + if (isLast) { + reservedSpaceForSlot = headerSize + linkSize // normal header size + size of the positive type which is the reference to the next object + isLast = false + } + result = result :+ currentEnvironment.reverse + currentEnvironment = List(variable) + } + } + result = result :+ currentEnvironment.reverse + + result.reverse + } + + /** + * When you have a big object to produce, you shard it into multiple slots instead of one single big slot. + * The end of each slot references to the next one. + * Each slot is 64 byte long + */ + private def produceShardedObject(role: String, environment: machine.Environment, freeInBody: Set[machine.Variable])(using ModuleContext, FunctionContext, BlockContext): Operand = { + // Split into multiple 64-byte blocks and chain them via a boxed link (%Pos with tag 0 pointing to next %Object) + val shardedEnvironments = splitEnvironment(environment) + + // Allocate the last block first. + val lastEnvironment = shardedEnvironments.last + val lastObjectReference = LocalReference(objectType, freshName(role)) + val lastEnvPtr = LocalReference(environmentType, freshName("environment")) + val lastSize = ConstantInt(environmentSize(lastEnvironment)) + val lastEraser = getEraser(lastEnvironment, ObjectEraser) + + emit(Call(lastObjectReference.name, Ccc(), objectType, newObject, List(lastEraser, lastSize))) + emit(Call(lastEnvPtr.name, Ccc(), environmentType, objectEnvironment, List(lastObjectReference))) + shareValues(lastEnvironment, freeInBody) + storeEnvironment(lastEnvPtr, lastEnvironment, Object) + + // Chain preceding blocks, each storing a boxed link to the next object + var headObject: LocalReference = lastObjectReference + + // loop through all shardedEnvironments except the last one in reversed order + shardedEnvironments.init.reverse.foreach { envChunk => + val temporaryName = freshName("link_temporary") + val linkValName = freshName("link") + + // we create a new Positive Object with tag 0... + emit(InsertValue(temporaryName, ConstantAggregateZero(positiveType), ConstantInt(0), 0)) // we create a fake Link Tag 0 that we just use for store a tag in the Pos + emit(InsertValue(linkValName, LocalReference(positiveType, temporaryName), headObject, 1)) + + // ... and inject it into our environment... + val extendedEnv = envChunk :+ machine.Variable(linkValName, machine.Positive()) + + // ...finally, we do the usual behavior when we produce an object + headObject = produceSingleObject(role, extendedEnv, freeInBody) + } + headObject + } + + /** + * Creates a new object and stores its environment in it + */ + private def produceSingleObject(role: String, environment: machine.Environment, freeInBody: Set[machine.Variable])(using ModuleContext, FunctionContext, BlockContext): LocalReference = { + val objectReference = LocalReference(objectType, freshName(role)) + val environmentReference = LocalReference(environmentType, freshName("environment")) + val size = ConstantInt(environmentSize(environment)) + val eraser = getEraser(environment, ObjectEraser) + + emit(Call(objectReference.name, Ccc(), objectType, newObject, List(eraser, size))); + emit(Call(environmentReference.name, Ccc(), environmentType, objectEnvironment, List(objectReference))); + shareValues(environment, freeInBody); + storeEnvironment(environmentReference, environment, Object); + objectReference + } + + private def loadAllVariables(pointer: Operand, environment: machine.Environment, alias: AliasInfo, typ: Type)(using ModuleContext, FunctionContext, BlockContext): Unit = { + environment.zipWithIndex.foreach { + case (machine.Variable(name, tpe), i) => + val field = LocalReference(PointerType(), freshName(name + "_pointer")) + emit(GetElementPtr(field.name, typ, pointer, List(0, i))) + emit(Load(name, transform(tpe), field, alias)) + } + } + + /** + * Creates an eraser for normal objects (e.g. Pos and Neg). + * When @eraseObject is called, we also call the eraser. And for Pos and Neg objects, that is the eraser. + * The object is called 2 times. + * 1. Phase: When call @eraseObject -> We call release to prepend the object to our to-do-list. + * 2. Phase: When call acquire -> We call %erase on each child, so the object can be reused again. + * + * @param freshEnvironment the variables of the object + * @return the eraser + */ + private def createEraserForNormalObjects(freshEnvironment: machine.Environment)(using C: ModuleContext): Operand = { + val eraser = ConstantGlobal(freshName("eraser")) + defineFunction(eraser.name, List(Parameter(objectType, "object"))) { + val objectRefCountPtr = LocalReference(PointerType(), freshName("objectReferenceCount")) + val referenceCount = LocalReference(referenceCountType, freshName("referenceCount")) + val releaseLabel = freshName("release") + val eraseChildrenLabel = freshName("eraseChildren") + + // Entry block: Check reference count to determine phase + // Switch: if refCount == 0, go to "release" (first phase), else "eraseChildren" (second phase) + // Note: When refCount == 0, this is the first call from eraseObject -> just release + // When refCount != 0, this is the second call from acquire -> erase children + emit(GetElementPtr(objectRefCountPtr.name, headerType, LocalReference(objectType, "object"), List(0, 0))) + emit(Load(referenceCount.name, referenceCountType, objectRefCountPtr, Object)) + + createAndEmitReleaseBasicBlock(releaseLabel) + createAndEmitEraseChildrenBasicBlock(freshEnvironment, eraseChildrenLabel) + + // Return switch terminator from entry block + Switch(referenceCount, eraseChildrenLabel, List((0, releaseLabel))) + } + + eraser + } + + private def createAndEmitReleaseBasicBlock(releaseLabel: String)(using ModuleContext, FunctionContext): Unit = { + emit(BasicBlock(releaseLabel, List( + Call("", Ccc(), VoidType(), ConstantGlobal("release"), List(LocalReference(objectType, "object"))) + ), RetVoid())) + } + + private def createAndEmitEraseChildrenBasicBlock(freshEnvironment: Environment, eraseChildrenLabel: String)(using ModuleContext, FunctionContext): Unit = { + val environmentRef = LocalReference(environmentType, freshName("environment")) + val eraseChildrenInstructions = mutable.ListBuffer[Instruction]() + + // Load environment variables and erase them + val envType = environmentType(freshEnvironment) + + val isAtLeastOneObjectToRelease: Boolean = + freshEnvironment.exists { + case machine.Variable(_, tpe) => + tpe match { + case machine.Positive() | machine.Negative() | machine.Type.Stack() => true + case _ => false + } + } + + if (isAtLeastOneObjectToRelease) { + // Get environment pointer + eraseChildrenInstructions += Call(environmentRef.name, Ccc(), environmentType, ConstantGlobal("objectEnvironment"), List(LocalReference(objectType, "object"))) + + freshEnvironment.zipWithIndex.foreach { case (machine.Variable(varName, tpe), i) => + val fieldPtr = LocalReference(PointerType(), freshName(varName + "_pointer")) + val loadedVarName = freshName(varName) + // Erase the value based on its type + tpe match { + case machine.Positive() => + emitElementPtrAndLoadOfEnvironmentVariable(environmentRef, eraseChildrenInstructions, envType, tpe, i, fieldPtr, loadedVarName) + eraseChildrenInstructions += Call("_", Ccc(), VoidType(), erasePositive, List(LocalReference(transform(tpe), loadedVarName))) + case machine.Negative() => + emitElementPtrAndLoadOfEnvironmentVariable(environmentRef, eraseChildrenInstructions, envType, tpe, i, fieldPtr, loadedVarName) + eraseChildrenInstructions += Call("_", Ccc(), VoidType(), eraseNegative, List(LocalReference(transform(tpe), loadedVarName))) + case machine.Type.Stack() => + emitElementPtrAndLoadOfEnvironmentVariable(environmentRef, eraseChildrenInstructions, envType, tpe, i, fieldPtr, loadedVarName) + eraseChildrenInstructions += Call("_", Ccc(), VoidType(), eraseResumption, List(LocalReference(transform(tpe), loadedVarName))) + case _ => // Int, Byte, Double, Reference, etc. don't need erasing + } + } + emit(BasicBlock(eraseChildrenLabel, eraseChildrenInstructions.toList, RetVoid())) + } else { + // If not: we can return immediately, since we don't need to erase anything + emit(BasicBlock(eraseChildrenLabel, eraseChildrenInstructions.toList, RetVoid())) + } + } + + private def emitElementPtrAndLoadOfEnvironmentVariable(environmentRef: LocalReference, eraseChildrenInstructions: ListBuffer[Instruction], envType: LLVMType, tpe: machine.Type, i: Int, fieldPtr: LocalReference, loadedVarName: String) = { + eraseChildrenInstructions += GetElementPtr(fieldPtr.name, envType, environmentRef, List(0, i)) + eraseChildrenInstructions += Load(loadedVarName, transform(tpe), fieldPtr, Object) + } } diff --git a/examples/flat/nooptimized/allocate_first_then_release_flush_once.check b/examples/flat/nooptimized/allocate_first_then_release_flush_once.check new file mode 100644 index 000000000..90fa4d6e3 --- /dev/null +++ b/examples/flat/nooptimized/allocate_first_then_release_flush_once.check @@ -0,0 +1,65 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 \ No newline at end of file diff --git a/examples/flat/nooptimized/allocate_first_then_release_flush_once.effekt b/examples/flat/nooptimized/allocate_first_then_release_flush_once.effekt new file mode 100644 index 000000000..4d1f729a1 --- /dev/null +++ b/examples/flat/nooptimized/allocate_first_then_release_flush_once.effekt @@ -0,0 +1,148 @@ + +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int +) + +def allocate65SlotsAndReleaseThem() = { + var x1 = OneSlotPerson(1, 2, 3, 4, 5, 6) + var x2 = OneSlotPerson(2, 3, 4, 5, 6, 7) + var x3 = OneSlotPerson(3, 4, 5, 6, 7, 8) + var x4 = OneSlotPerson(4, 5, 6, 7, 8, 9) + var x5 = OneSlotPerson(5, 6, 7, 8, 9, 10) + var x6 = OneSlotPerson(6, 7, 8, 9, 10, 11) + var x7 = OneSlotPerson(7, 8, 9, 10, 11, 12) + var x8 = OneSlotPerson(8, 9, 10, 11, 12, 13) + var x9 = OneSlotPerson(9, 10, 11, 12, 13, 14) + var x10 = OneSlotPerson(10, 11, 12, 13, 14, 15) + var x11 = OneSlotPerson(11, 12, 13, 14, 15, 16) + var x12 = OneSlotPerson(12, 13, 14, 15, 16, 17) + var x13 = OneSlotPerson(13, 14, 15, 16, 17, 18) + var x14 = OneSlotPerson(14, 15, 16, 17, 18, 19) + var x15 = OneSlotPerson(15, 16, 17, 18, 19, 20) + var x16 = OneSlotPerson(16, 17, 18, 19, 20, 21) + var x17 = OneSlotPerson(17, 18, 19, 20, 21, 22) + var x18 = OneSlotPerson(18, 19, 20, 21, 22, 23) + var x19 = OneSlotPerson(19, 20, 21, 22, 23, 24) + var x20 = OneSlotPerson(20, 21, 22, 23, 24, 25) + var x21 = OneSlotPerson(21, 22, 23, 24, 25, 26) + var x22 = OneSlotPerson(22, 23, 24, 25, 26, 27) + var x23 = OneSlotPerson(23, 24, 25, 26, 27, 28) + var x24 = OneSlotPerson(24, 25, 26, 27, 28, 29) + var x25 = OneSlotPerson(25, 26, 27, 28, 29, 30) + var x26 = OneSlotPerson(26, 27, 28, 29, 30, 31) + var x27 = OneSlotPerson(27, 28, 29, 30, 31, 32) + var x28 = OneSlotPerson(28, 29, 30, 31, 32, 33) + var x29 = OneSlotPerson(29, 30, 31, 32, 33, 34) + var x30 = OneSlotPerson(30, 31, 32, 33, 34, 35) + var x31 = OneSlotPerson(31, 32, 33, 34, 35, 36) + var x32 = OneSlotPerson(32, 33, 34, 35, 36, 37) + var x33 = OneSlotPerson(33, 34, 35, 36, 37, 38) + var x34 = OneSlotPerson(34, 35, 36, 37, 38, 39) + var x35 = OneSlotPerson(35, 36, 37, 38, 39, 40) + var x36 = OneSlotPerson(36, 37, 38, 39, 40, 41) + var x37 = OneSlotPerson(37, 38, 39, 40, 41, 42) + var x38 = OneSlotPerson(38, 39, 40, 41, 42, 43) + var x39 = OneSlotPerson(39, 40, 41, 42, 43, 44) + var x40 = OneSlotPerson(40, 41, 42, 43, 44, 45) + var x41 = OneSlotPerson(41, 42, 43, 44, 45, 46) + var x42 = OneSlotPerson(42, 43, 44, 45, 46, 47) + var x43 = OneSlotPerson(43, 44, 45, 46, 47, 48) + var x44 = OneSlotPerson(44, 45, 46, 47, 48, 49) + var x45 = OneSlotPerson(45, 46, 47, 48, 49, 50) + var x46 = OneSlotPerson(46, 47, 48, 49, 50, 51) + var x47 = OneSlotPerson(47, 48, 49, 50, 51, 52) + var x48 = OneSlotPerson(48, 49, 50, 51, 52, 53) + var x49 = OneSlotPerson(49, 50, 51, 52, 53, 54) + var x50 = OneSlotPerson(50, 51, 52, 53, 54, 55) + var x51 = OneSlotPerson(51, 52, 53, 54, 55, 56) + var x52 = OneSlotPerson(52, 53, 54, 55, 56, 57) + var x53 = OneSlotPerson(53, 54, 55, 56, 57, 58) + var x54 = OneSlotPerson(54, 55, 56, 57, 58, 59) + var x55 = OneSlotPerson(55, 56, 57, 58, 59, 60) + var x56 = OneSlotPerson(56, 57, 58, 59, 60, 61) + var x57 = OneSlotPerson(57, 58, 59, 60, 61, 62) + var x58 = OneSlotPerson(58, 59, 60, 61, 62, 63) + var x59 = OneSlotPerson(59, 60, 61, 62, 63, 64) + var x60 = OneSlotPerson(60, 61, 62, 63, 64, 65) + var x61 = OneSlotPerson(61, 62, 63, 64, 65, 66) + var x62 = OneSlotPerson(62, 63, 64, 65, 66, 67) + var x63 = OneSlotPerson(63, 64, 65, 66, 67, 68) + var x64 = OneSlotPerson(64, 65, 66, 67, 68, 69) + var x65 = OneSlotPerson(65, 66, 67, 68, 69, 70) + + println(x1.field1) + println(x2.field1) + println(x3.field1) + println(x4.field1) + println(x5.field1) + println(x6.field1) + println(x7.field1) + println(x8.field1) + println(x9.field1) + println(x10.field1) + println(x11.field1) + println(x12.field1) + println(x13.field1) + println(x14.field1) + println(x15.field1) + println(x16.field1) + println(x17.field1) + println(x18.field1) + println(x19.field1) + println(x20.field1) + println(x21.field1) + println(x22.field1) + println(x23.field1) + println(x24.field1) + println(x25.field1) + println(x26.field1) + println(x27.field1) + println(x28.field1) + println(x29.field1) + println(x30.field1) + println(x31.field1) + println(x32.field1) + println(x33.field1) + println(x34.field1) + println(x35.field1) + println(x36.field1) + println(x37.field1) + println(x38.field1) + println(x39.field1) + println(x40.field1) + println(x41.field1) + println(x42.field1) + println(x43.field1) + println(x44.field1) + println(x45.field1) + println(x46.field1) + println(x47.field1) + println(x48.field1) + println(x49.field1) + println(x50.field1) + println(x51.field1) + println(x52.field1) + println(x53.field1) + println(x54.field1) + println(x55.field1) + println(x56.field1) + println(x57.field1) + println(x58.field1) + println(x59.field1) + println(x60.field1) + println(x61.field1) + println(x62.field1) + println(x63.field1) + println(x64.field1) + println(x65.field1) +} + +def main() = { + allocate65SlotsAndReleaseThem(); + var finalObjectThatTriggersFlushingTodoList = OneSlotPerson(1, 2, 3, 4, 5, 6) +} diff --git a/examples/flat/nooptimized/allocate_first_then_release_flush_twice.check b/examples/flat/nooptimized/allocate_first_then_release_flush_twice.check new file mode 100644 index 000000000..e69de29bb diff --git a/examples/flat/nooptimized/allocate_first_then_release_flush_twice.effekt b/examples/flat/nooptimized/allocate_first_then_release_flush_twice.effekt new file mode 100644 index 000000000..d9b4ccbb5 --- /dev/null +++ b/examples/flat/nooptimized/allocate_first_then_release_flush_twice.effekt @@ -0,0 +1,282 @@ + +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int +) + +// we first allocate 128 slots and then release them all, such that we have exactly 128 slots on the to-do-list +// therefore, we have to flush the to-do list twice to clear it completely +def allocate128SlotsAndReleaseThem() = { + var x1 = OneSlotPerson(1, 2, 3, 4, 5, 6) + var x2 = OneSlotPerson(2, 3, 4, 5, 6, 7) + var x3 = OneSlotPerson(3, 4, 5, 6, 7, 8) + var x4 = OneSlotPerson(4, 5, 6, 7, 8, 9) + var x5 = OneSlotPerson(5, 6, 7, 8, 9, 10) + var x6 = OneSlotPerson(6, 7, 8, 9, 10, 11) + var x7 = OneSlotPerson(7, 8, 9, 10, 11, 12) + var x8 = OneSlotPerson(8, 9, 10, 11, 12, 13) + var x9 = OneSlotPerson(9, 10, 11, 12, 13, 14) + var x10 = OneSlotPerson(10, 11, 12, 13, 14, 15) + var x11 = OneSlotPerson(11, 12, 13, 14, 15, 16) + var x12 = OneSlotPerson(12, 13, 14, 15, 16, 17) + var x13 = OneSlotPerson(13, 14, 15, 16, 17, 18) + var x14 = OneSlotPerson(14, 15, 16, 17, 18, 19) + var x15 = OneSlotPerson(15, 16, 17, 18, 19, 20) + var x16 = OneSlotPerson(16, 17, 18, 19, 20, 21) + var x17 = OneSlotPerson(17, 18, 19, 20, 21, 22) + var x18 = OneSlotPerson(18, 19, 20, 21, 22, 23) + var x19 = OneSlotPerson(19, 20, 21, 22, 23, 24) + var x20 = OneSlotPerson(20, 21, 22, 23, 24, 25) + var x21 = OneSlotPerson(21, 22, 23, 24, 25, 26) + var x22 = OneSlotPerson(22, 23, 24, 25, 26, 27) + var x23 = OneSlotPerson(23, 24, 25, 26, 27, 28) + var x24 = OneSlotPerson(24, 25, 26, 27, 28, 29) + var x25 = OneSlotPerson(25, 26, 27, 28, 29, 30) + var x26 = OneSlotPerson(26, 27, 28, 29, 30, 31) + var x27 = OneSlotPerson(27, 28, 29, 30, 31, 32) + var x28 = OneSlotPerson(28, 29, 30, 31, 32, 33) + var x29 = OneSlotPerson(29, 30, 31, 32, 33, 34) + var x30 = OneSlotPerson(30, 31, 32, 33, 34, 35) + var x31 = OneSlotPerson(31, 32, 33, 34, 35, 36) + var x32 = OneSlotPerson(32, 33, 34, 35, 36, 37) + var x33 = OneSlotPerson(33, 34, 35, 36, 37, 38) + var x34 = OneSlotPerson(34, 35, 36, 37, 38, 39) + var x35 = OneSlotPerson(35, 36, 37, 38, 39, 40) + var x36 = OneSlotPerson(36, 37, 38, 39, 40, 41) + var x37 = OneSlotPerson(37, 38, 39, 40, 41, 42) + var x38 = OneSlotPerson(38, 39, 40, 41, 42, 43) + var x39 = OneSlotPerson(39, 40, 41, 42, 43, 44) + var x40 = OneSlotPerson(40, 41, 42, 43, 44, 45) + var x41 = OneSlotPerson(41, 42, 43, 44, 45, 46) + var x42 = OneSlotPerson(42, 43, 44, 45, 46, 47) + var x43 = OneSlotPerson(43, 44, 45, 46, 47, 48) + var x44 = OneSlotPerson(44, 45, 46, 47, 48, 49) + var x45 = OneSlotPerson(45, 46, 47, 48, 49, 50) + var x46 = OneSlotPerson(46, 47, 48, 49, 50, 51) + var x47 = OneSlotPerson(47, 48, 49, 50, 51, 52) + var x48 = OneSlotPerson(48, 49, 50, 51, 52, 53) + var x49 = OneSlotPerson(49, 50, 51, 52, 53, 54) + var x50 = OneSlotPerson(50, 51, 52, 53, 54, 55) + var x51 = OneSlotPerson(51, 52, 53, 54, 55, 56) + var x52 = OneSlotPerson(52, 53, 54, 55, 56, 57) + var x53 = OneSlotPerson(53, 54, 55, 56, 57, 58) + var x54 = OneSlotPerson(54, 55, 56, 57, 58, 59) + var x55 = OneSlotPerson(55, 56, 57, 58, 59, 60) + var x56 = OneSlotPerson(56, 57, 58, 59, 60, 61) + var x57 = OneSlotPerson(57, 58, 59, 60, 61, 62) + var x58 = OneSlotPerson(58, 59, 60, 61, 62, 63) + var x59 = OneSlotPerson(59, 60, 61, 62, 63, 64) + var x60 = OneSlotPerson(60, 61, 62, 63, 64, 65) + var x61 = OneSlotPerson(61, 62, 63, 64, 65, 66) + var x62 = OneSlotPerson(62, 63, 64, 65, 66, 67) + var x63 = OneSlotPerson(63, 64, 65, 66, 67, 68) + var x64 = OneSlotPerson(64, 65, 66, 67, 68, 69) + var x65 = OneSlotPerson(65, 66, 67, 68, 69, 70) + var x66 = OneSlotPerson(66, 67, 68, 69, 70, 71) + var x67 = OneSlotPerson(67, 68, 69, 70, 71, 72) + var x68 = OneSlotPerson(68, 69, 70, 71, 72, 73) + var x69 = OneSlotPerson(69, 70, 71, 72, 73, 74) + var x70 = OneSlotPerson(70, 71, 72, 73, 74, 75) + var x71 = OneSlotPerson(71, 72, 73, 74, 75, 76) + var x72 = OneSlotPerson(72, 73, 74, 75, 76, 77) + var x73 = OneSlotPerson(73, 74, 75, 76, 77, 78) + var x74 = OneSlotPerson(74, 75, 76, 77, 78, 79) + var x75 = OneSlotPerson(75, 76, 77, 78, 79, 80) + var x76 = OneSlotPerson(76, 77, 78, 79, 80, 81) + var x77 = OneSlotPerson(77, 78, 79, 80, 81, 82) + var x78 = OneSlotPerson(78, 79, 80, 81, 82, 83) + var x79 = OneSlotPerson(79, 80, 81, 82, 83, 84) + var x80 = OneSlotPerson(80, 81, 82, 83, 84, 85) + var x81 = OneSlotPerson(81, 82, 83, 84, 85, 86) + var x82 = OneSlotPerson(82, 83, 84, 85, 86, 87) + var x83 = OneSlotPerson(83, 84, 85, 86, 87, 88) + var x84 = OneSlotPerson(84, 85, 86, 87, 88, 89) + var x85 = OneSlotPerson(85, 86, 87, 88, 89, 90) + var x86 = OneSlotPerson(86, 87, 88, 89, 90, 91) + var x87 = OneSlotPerson(87, 88, 89, 90, 91, 92) + var x88 = OneSlotPerson(88, 89, 90, 91, 92, 93) + var x89 = OneSlotPerson(89, 90, 91, 92, 93, 94) + var x90 = OneSlotPerson(90, 91, 92, 93, 94, 95) + var x91 = OneSlotPerson(91, 92, 93, 94, 95, 96) + var x92 = OneSlotPerson(92, 93, 94, 95, 96, 97) + var x93 = OneSlotPerson(93, 94, 95, 96, 97, 98) + var x94 = OneSlotPerson(94, 95, 96, 97, 98, 99) + var x95 = OneSlotPerson(95, 96, 97, 98, 99, 100) + var x96 = OneSlotPerson(96, 97, 98, 99, 100, 101) + var x97 = OneSlotPerson(97, 98, 99, 100, 101, 102) + var x98 = OneSlotPerson(98, 99, 100, 101, 102, 103) + var x99 = OneSlotPerson(99, 100, 101, 102, 103, 104) + var x100 = OneSlotPerson(100, 101, 102, 103, 104, 105) + var x101 = OneSlotPerson(101, 102, 103, 104, 105, 106) + var x102 = OneSlotPerson(102, 103, 104, 105, 106, 107) + var x103 = OneSlotPerson(103, 104, 105, 106, 107, 108) + var x104 = OneSlotPerson(104, 105, 106, 107, 108, 109) + var x105 = OneSlotPerson(105, 106, 107, 108, 109, 110) + var x106 = OneSlotPerson(106, 107, 108, 109, 110, 111) + var x107 = OneSlotPerson(107, 108, 109, 110, 111, 112) + var x108 = OneSlotPerson(108, 109, 110, 111, 112, 113) + var x109 = OneSlotPerson(109, 110, 111, 112, 113, 114) + var x110 = OneSlotPerson(110, 111, 112, 113, 114, 115) + var x111 = OneSlotPerson(111, 112, 113, 114, 115, 116) + var x112 = OneSlotPerson(112, 113, 114, 115, 116, 117) + var x113 = OneSlotPerson(113, 114, 115, 116, 117, 118) + var x114 = OneSlotPerson(114, 115, 116, 117, 118, 119) + var x115 = OneSlotPerson(115, 116, 117, 118, 119, 120) + var x116 = OneSlotPerson(116, 117, 118, 119, 120, 121) + var x117 = OneSlotPerson(117, 118, 119, 120, 121, 122) + var x118 = OneSlotPerson(118, 119, 120, 121, 122, 123) + var x119 = OneSlotPerson(119, 120, 121, 122, 123, 124) + var x120 = OneSlotPerson(120, 121, 122, 123, 124, 125) + var x121 = OneSlotPerson(121, 122, 123, 124, 125, 126) + var x122 = OneSlotPerson(122, 123, 124, 125, 126, 127) + var x123 = OneSlotPerson(123, 124, 125, 126, 127, 128) + var x124 = OneSlotPerson(124, 125, 126, 127, 128, 129) + var x125 = OneSlotPerson(125, 126, 127, 128, 129, 130) + var x126 = OneSlotPerson(126, 127, 128, 129, 130, 131) + var x127 = OneSlotPerson(127, 128, 129, 130, 131, 132) + var x128 = OneSlotPerson(128, 129, 130, 131, 132, 133) + + println(x1.field1) + println(x2.field1) + println(x3.field1) + println(x4.field1) + println(x5.field1) + println(x6.field1) + println(x7.field1) + println(x8.field1) + println(x9.field1) + println(x10.field1) + println(x11.field1) + println(x12.field1) + println(x13.field1) + println(x14.field1) + println(x15.field1) + println(x16.field1) + println(x17.field1) + println(x18.field1) + println(x19.field1) + println(x20.field1) + println(x21.field1) + println(x22.field1) + println(x23.field1) + println(x24.field1) + println(x25.field1) + println(x26.field1) + println(x27.field1) + println(x28.field1) + println(x29.field1) + println(x30.field1) + println(x31.field1) + println(x32.field1) + println(x33.field1) + println(x34.field1) + println(x35.field1) + println(x36.field1) + println(x37.field1) + println(x38.field1) + println(x39.field1) + println(x40.field1) + println(x41.field1) + println(x42.field1) + println(x43.field1) + println(x44.field1) + println(x45.field1) + println(x46.field1) + println(x47.field1) + println(x48.field1) + println(x49.field1) + println(x50.field1) + println(x51.field1) + println(x52.field1) + println(x53.field1) + println(x54.field1) + println(x55.field1) + println(x56.field1) + println(x57.field1) + println(x58.field1) + println(x59.field1) + println(x60.field1) + println(x61.field1) + println(x62.field1) + println(x63.field1) + println(x64.field1) + println(x65.field1) + println(x66.field1) + println(x67.field1) + println(x68.field1) + println(x69.field1) + println(x70.field1) + println(x71.field1) + println(x72.field1) + println(x73.field1) + println(x74.field1) + println(x75.field1) + println(x76.field1) + println(x77.field1) + println(x78.field1) + println(x79.field1) + println(x80.field1) + println(x81.field1) + println(x82.field1) + println(x83.field1) + println(x84.field1) + println(x85.field1) + println(x86.field1) + println(x87.field1) + println(x88.field1) + println(x89.field1) + println(x90.field1) + println(x91.field1) + println(x92.field1) + println(x93.field1) + println(x94.field1) + println(x95.field1) + println(x96.field1) + println(x97.field1) + println(x98.field1) + println(x99.field1) + println(x100.field1) + println(x101.field1) + println(x102.field1) + println(x103.field1) + println(x104.field1) + println(x105.field1) + println(x106.field1) + println(x107.field1) + println(x108.field1) + println(x109.field1) + println(x110.field1) + println(x111.field1) + println(x112.field1) + println(x113.field1) + println(x114.field1) + println(x115.field1) + println(x116.field1) + println(x117.field1) + println(x118.field1) + println(x119.field1) + println(x120.field1) + println(x121.field1) + println(x122.field1) + println(x123.field1) + println(x124.field1) + println(x125.field1) + println(x126.field1) + println(x127.field1) + println(x128.field1) +} + +def main() = { + //allocate128SlotsAndReleaseThem(); + // allocate & flush to-do list twice + //var flushingTodoListFirstTime = OneSlotPerson(1, 2, 3, 4, 5, 6) + //var flushingTodoListSecondTime = OneSlotPerson(1, 2, 3, 4, 5, 7) + + // deallocate again + //println(flushingTodoListFirstTime.field1) + //println(flushingTodoListSecondTime.field1) +} diff --git a/examples/flat/nooptimized/array_record.check b/examples/flat/nooptimized/array_record.check new file mode 100644 index 000000000..56ea89185 --- /dev/null +++ b/examples/flat/nooptimized/array_record.check @@ -0,0 +1 @@ +Array(1, 2, 3) \ No newline at end of file diff --git a/examples/flat/nooptimized/array_record.effekt b/examples/flat/nooptimized/array_record.effekt new file mode 100644 index 000000000..0580fbeae --- /dev/null +++ b/examples/flat/nooptimized/array_record.effekt @@ -0,0 +1,10 @@ +record Person( + field1: Int, + field2: Array[Int] + ) + +def main() = { + val myArray: Array[Int] = build(3) { i => i + 1 } // Array(1, 2, 3) + val p = Person(1, myArray) + println(myArray) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/different_person_sizes_biggest_first.check b/examples/flat/nooptimized/different_person_sizes_biggest_first.check new file mode 100644 index 000000000..63ea17a09 --- /dev/null +++ b/examples/flat/nooptimized/different_person_sizes_biggest_first.check @@ -0,0 +1,3 @@ +24 +13 +6 \ No newline at end of file diff --git a/examples/flat/nooptimized/different_person_sizes_biggest_first.effekt b/examples/flat/nooptimized/different_person_sizes_biggest_first.effekt new file mode 100644 index 000000000..6a963c745 --- /dev/null +++ b/examples/flat/nooptimized/different_person_sizes_biggest_first.effekt @@ -0,0 +1,46 @@ +// this test is for debugging of the to-do-list approach. Here, we define multiple records that require different +// number of heap-slots (aka. 64 bytes). + +// here we allocate the biggest object at first and go to the smallest. + +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int + ) + +record TwoSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int + ) + +record ThreeSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int + ) + +def main() = { + val p3 = ThreeSlotPerson(14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24) + println(p3.field11) + val p2 = TwoSlotPerson(7, 8, 9, 10, 11, 12, 13) + println(p2.field7) + val p1 = OneSlotPerson(1, 2, 3, 4, 5, 6) + println(p1.field6) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/different_person_sizes_smallest_first.check b/examples/flat/nooptimized/different_person_sizes_smallest_first.check new file mode 100644 index 000000000..bdfbf007c --- /dev/null +++ b/examples/flat/nooptimized/different_person_sizes_smallest_first.check @@ -0,0 +1,3 @@ +6 +13 +26 \ No newline at end of file diff --git a/examples/flat/nooptimized/different_person_sizes_smallest_first.effekt b/examples/flat/nooptimized/different_person_sizes_smallest_first.effekt new file mode 100644 index 000000000..2a61b272d --- /dev/null +++ b/examples/flat/nooptimized/different_person_sizes_smallest_first.effekt @@ -0,0 +1,46 @@ +// this test is for debugging of the to-do-list approach. Here, we define multiple records that require different +// number of heap-slots (aka. 64 bytes). + +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int + ) + +record TwoSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int + ) + +record ThreeSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int, + field12: Int, + field13: Int + ) + +def main() = { + val p1 = OneSlotPerson(1, 2, 3, 4, 5, 6) + println(p1.field6) + val p2 = TwoSlotPerson(7, 8, 9, 10, 11, 12, 13) + println(p2.field7) + val p3 = ThreeSlotPerson(14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26) + println(p3.field13) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/nested_objects.check b/examples/flat/nooptimized/nested_objects.check new file mode 100644 index 000000000..e440e5c84 --- /dev/null +++ b/examples/flat/nooptimized/nested_objects.check @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/examples/flat/nooptimized/nested_objects.effekt b/examples/flat/nooptimized/nested_objects.effekt new file mode 100644 index 000000000..27a274b5f --- /dev/null +++ b/examples/flat/nooptimized/nested_objects.effekt @@ -0,0 +1,16 @@ +record Person1( + field3: Int, + field4: Int +) + +record Person( + field1: Int, + field2: Int, + person1: Person1 + ) + +def main() = { + val p1 = Person1(3, 4) + val p = Person(1, 2, p1) + println(p.person1.field3) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_big_string_object.check b/examples/flat/nooptimized/one_big_string_object.check new file mode 100644 index 000000000..41bfe81b8 --- /dev/null +++ b/examples/flat/nooptimized/one_big_string_object.check @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. \ No newline at end of file diff --git a/examples/flat/nooptimized/one_big_string_object.effekt b/examples/flat/nooptimized/one_big_string_object.effekt new file mode 100644 index 000000000..492ee575c --- /dev/null +++ b/examples/flat/nooptimized/one_big_string_object.effekt @@ -0,0 +1,9 @@ +// contains one big lorem ipsum string with 100 words +record Person( + field1: String + ) + +def main() = { + val p = Person("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.") + println(p.field1) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_lg_object.check b/examples/flat/nooptimized/one_lg_object.check new file mode 100644 index 000000000..9a037142a --- /dev/null +++ b/examples/flat/nooptimized/one_lg_object.check @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/examples/flat/nooptimized/one_lg_object.effekt b/examples/flat/nooptimized/one_lg_object.effekt new file mode 100644 index 000000000..18eff9264 --- /dev/null +++ b/examples/flat/nooptimized/one_lg_object.effekt @@ -0,0 +1,18 @@ +// lg = Person fills 2 saving slots completely +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int + ) + +def main() = { + val p = Person(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + println(p.field10) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_md_object.check b/examples/flat/nooptimized/one_md_object.check new file mode 100644 index 000000000..c7930257d --- /dev/null +++ b/examples/flat/nooptimized/one_md_object.check @@ -0,0 +1 @@ +7 \ No newline at end of file diff --git a/examples/flat/nooptimized/one_md_object.effekt b/examples/flat/nooptimized/one_md_object.effekt new file mode 100644 index 000000000..d68c5a960 --- /dev/null +++ b/examples/flat/nooptimized/one_md_object.effekt @@ -0,0 +1,15 @@ +// md = Person requires 2 saving slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int + ) + +def main() = { + val p = Person(1, 2, 3, 4, 5, 6, 7) + println(p.field7) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_sm_object.check b/examples/flat/nooptimized/one_sm_object.check new file mode 100644 index 000000000..62f945751 --- /dev/null +++ b/examples/flat/nooptimized/one_sm_object.check @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/examples/flat/nooptimized/one_sm_object.effekt b/examples/flat/nooptimized/one_sm_object.effekt new file mode 100644 index 000000000..95ffb2305 --- /dev/null +++ b/examples/flat/nooptimized/one_sm_object.effekt @@ -0,0 +1,14 @@ +// sm = Person fills 1 saving slot completely +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int + ) + +def main() = { + val p = Person(1, 2, 3, 4, 5, 6) + println(p.field6) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_small_string_object.check b/examples/flat/nooptimized/one_small_string_object.check new file mode 100644 index 000000000..30d74d258 --- /dev/null +++ b/examples/flat/nooptimized/one_small_string_object.check @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/examples/flat/nooptimized/one_small_string_object.effekt b/examples/flat/nooptimized/one_small_string_object.effekt new file mode 100644 index 000000000..efe6e6fef --- /dev/null +++ b/examples/flat/nooptimized/one_small_string_object.effekt @@ -0,0 +1,8 @@ +record Person( + field1: String + ) + +def main() = { + val p = Person("test") + println(p.field1) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xl_object.check b/examples/flat/nooptimized/one_xl_object.check new file mode 100644 index 000000000..9d607966b --- /dev/null +++ b/examples/flat/nooptimized/one_xl_object.check @@ -0,0 +1 @@ +11 \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xl_object.effekt b/examples/flat/nooptimized/one_xl_object.effekt new file mode 100644 index 000000000..bc45859ca --- /dev/null +++ b/examples/flat/nooptimized/one_xl_object.effekt @@ -0,0 +1,19 @@ +// xl = Person needs 3 saving slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int + ) + +def main() = { + val p = Person(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) + println(p.field11) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xs_object.check b/examples/flat/nooptimized/one_xs_object.check new file mode 100644 index 000000000..e440e5c84 --- /dev/null +++ b/examples/flat/nooptimized/one_xs_object.check @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xs_object.effekt b/examples/flat/nooptimized/one_xs_object.effekt new file mode 100644 index 000000000..034c32ea5 --- /dev/null +++ b/examples/flat/nooptimized/one_xs_object.effekt @@ -0,0 +1,11 @@ +// xs = Person fits easily in 1 saving slot +record Person( + field1: Int, + field2: Int, + field3: Int + ) + +def main() = { + val p = Person(1, 2, 3) + println(p.field3) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xxl_object_all_fields.check b/examples/flat/nooptimized/one_xxl_object_all_fields.check new file mode 100644 index 000000000..6a0bcb871 --- /dev/null +++ b/examples/flat/nooptimized/one_xxl_object_all_fields.check @@ -0,0 +1,100 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xxl_object_all_fields.effekt b/examples/flat/nooptimized/one_xxl_object_all_fields.effekt new file mode 100644 index 000000000..824a4b603 --- /dev/null +++ b/examples/flat/nooptimized/one_xxl_object_all_fields.effekt @@ -0,0 +1,308 @@ +// xxl: Person has 100 fields -> need x slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int, + field12: Int, + field13: Int, + field14: Int, + field15: Int, + field16: Int, + field17: Int, + field18: Int, + field19: Int, + field20: Int, + field21: Int, + field22: Int, + field23: Int, + field24: Int, + field25: Int, + field26: Int, + field27: Int, + field28: Int, + field29: Int, + field30: Int, + field31: Int, + field32: Int, + field33: Int, + field34: Int, + field35: Int, + field36: Int, + field37: Int, + field38: Int, + field39: Int, + field40: Int, + field41: Int, + field42: Int, + field43: Int, + field44: Int, + field45: Int, + field46: Int, + field47: Int, + field48: Int, + field49: Int, + field50: Int, + field51: Int, + field52: Int, + field53: Int, + field54: Int, + field55: Int, + field56: Int, + field57: Int, + field58: Int, + field59: Int, + field60: Int, + field61: Int, + field62: Int, + field63: Int, + field64: Int, + field65: Int, + field66: Int, + field67: Int, + field68: Int, + field69: Int, + field70: Int, + field71: Int, + field72: Int, + field73: Int, + field74: Int, + field75: Int, + field76: Int, + field77: Int, + field78: Int, + field79: Int, + field80: Int, + field81: Int, + field82: Int, + field83: Int, + field84: Int, + field85: Int, + field86: Int, + field87: Int, + field88: Int, + field89: Int, + field90: Int, + field91: Int, + field92: Int, + field93: Int, + field94: Int, + field95: Int, + field96: Int, + field97: Int, + field98: Int, + field99: Int, + field100: Int +) + +def main() = { + val p1 = Person( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100 +) + println(p1.field1) + println(p1.field2) + println(p1.field3) + println(p1.field4) + println(p1.field5) + println(p1.field6) + println(p1.field7) + println(p1.field8) + println(p1.field9) + println(p1.field10) + println(p1.field11) + println(p1.field12) + println(p1.field13) + println(p1.field14) + println(p1.field15) + println(p1.field16) + println(p1.field17) + println(p1.field18) + println(p1.field19) + println(p1.field20) + println(p1.field21) + println(p1.field22) + println(p1.field23) + println(p1.field24) + println(p1.field25) + println(p1.field26) + println(p1.field27) + println(p1.field28) + println(p1.field29) + println(p1.field30) + println(p1.field31) + println(p1.field32) + println(p1.field33) + println(p1.field34) + println(p1.field35) + println(p1.field36) + println(p1.field37) + println(p1.field38) + println(p1.field39) + println(p1.field40) + println(p1.field41) + println(p1.field42) + println(p1.field43) + println(p1.field44) + println(p1.field45) + println(p1.field46) + println(p1.field47) + println(p1.field48) + println(p1.field49) + println(p1.field50) + println(p1.field51) + println(p1.field52) + println(p1.field53) + println(p1.field54) + println(p1.field55) + println(p1.field56) + println(p1.field57) + println(p1.field58) + println(p1.field59) + println(p1.field60) + println(p1.field61) + println(p1.field62) + println(p1.field63) + println(p1.field64) + println(p1.field65) + println(p1.field66) + println(p1.field67) + println(p1.field68) + println(p1.field69) + println(p1.field70) + println(p1.field71) + println(p1.field72) + println(p1.field73) + println(p1.field74) + println(p1.field75) + println(p1.field76) + println(p1.field77) + println(p1.field78) + println(p1.field79) + println(p1.field80) + println(p1.field81) + println(p1.field82) + println(p1.field83) + println(p1.field84) + println(p1.field85) + println(p1.field86) + println(p1.field87) + println(p1.field88) + println(p1.field89) + println(p1.field90) + println(p1.field91) + println(p1.field92) + println(p1.field93) + println(p1.field94) + println(p1.field95) + println(p1.field96) + println(p1.field97) + println(p1.field98) + println(p1.field99) + println(p1.field100) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xxxl_object.check b/examples/flat/nooptimized/one_xxxl_object.check new file mode 100644 index 000000000..eb1f49486 --- /dev/null +++ b/examples/flat/nooptimized/one_xxxl_object.check @@ -0,0 +1 @@ +500 \ No newline at end of file diff --git a/examples/flat/nooptimized/one_xxxl_object.effekt b/examples/flat/nooptimized/one_xxxl_object.effekt new file mode 100644 index 000000000..74211407a --- /dev/null +++ b/examples/flat/nooptimized/one_xxxl_object.effekt @@ -0,0 +1,1008 @@ +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int, + field12: Int, + field13: Int, + field14: Int, + field15: Int, + field16: Int, + field17: Int, + field18: Int, + field19: Int, + field20: Int, + field21: Int, + field22: Int, + field23: Int, + field24: Int, + field25: Int, + field26: Int, + field27: Int, + field28: Int, + field29: Int, + field30: Int, + field31: Int, + field32: Int, + field33: Int, + field34: Int, + field35: Int, + field36: Int, + field37: Int, + field38: Int, + field39: Int, + field40: Int, + field41: Int, + field42: Int, + field43: Int, + field44: Int, + field45: Int, + field46: Int, + field47: Int, + field48: Int, + field49: Int, + field50: Int, + field51: Int, + field52: Int, + field53: Int, + field54: Int, + field55: Int, + field56: Int, + field57: Int, + field58: Int, + field59: Int, + field60: Int, + field61: Int, + field62: Int, + field63: Int, + field64: Int, + field65: Int, + field66: Int, + field67: Int, + field68: Int, + field69: Int, + field70: Int, + field71: Int, + field72: Int, + field73: Int, + field74: Int, + field75: Int, + field76: Int, + field77: Int, + field78: Int, + field79: Int, + field80: Int, + field81: Int, + field82: Int, + field83: Int, + field84: Int, + field85: Int, + field86: Int, + field87: Int, + field88: Int, + field89: Int, + field90: Int, + field91: Int, + field92: Int, + field93: Int, + field94: Int, + field95: Int, + field96: Int, + field97: Int, + field98: Int, + field99: Int, + field100: Int, + field101: Int, + field102: Int, + field103: Int, + field104: Int, + field105: Int, + field106: Int, + field107: Int, + field108: Int, + field109: Int, + field110: Int, + field111: Int, + field112: Int, + field113: Int, + field114: Int, + field115: Int, + field116: Int, + field117: Int, + field118: Int, + field119: Int, + field120: Int, + field121: Int, + field122: Int, + field123: Int, + field124: Int, + field125: Int, + field126: Int, + field127: Int, + field128: Int, + field129: Int, + field130: Int, + field131: Int, + field132: Int, + field133: Int, + field134: Int, + field135: Int, + field136: Int, + field137: Int, + field138: Int, + field139: Int, + field140: Int, + field141: Int, + field142: Int, + field143: Int, + field144: Int, + field145: Int, + field146: Int, + field147: Int, + field148: Int, + field149: Int, + field150: Int, + field151: Int, + field152: Int, + field153: Int, + field154: Int, + field155: Int, + field156: Int, + field157: Int, + field158: Int, + field159: Int, + field160: Int, + field161: Int, + field162: Int, + field163: Int, + field164: Int, + field165: Int, + field166: Int, + field167: Int, + field168: Int, + field169: Int, + field170: Int, + field171: Int, + field172: Int, + field173: Int, + field174: Int, + field175: Int, + field176: Int, + field177: Int, + field178: Int, + field179: Int, + field180: Int, + field181: Int, + field182: Int, + field183: Int, + field184: Int, + field185: Int, + field186: Int, + field187: Int, + field188: Int, + field189: Int, + field190: Int, + field191: Int, + field192: Int, + field193: Int, + field194: Int, + field195: Int, + field196: Int, + field197: Int, + field198: Int, + field199: Int, + field200: Int, + field201: Int, + field202: Int, + field203: Int, + field204: Int, + field205: Int, + field206: Int, + field207: Int, + field208: Int, + field209: Int, + field210: Int, + field211: Int, + field212: Int, + field213: Int, + field214: Int, + field215: Int, + field216: Int, + field217: Int, + field218: Int, + field219: Int, + field220: Int, + field221: Int, + field222: Int, + field223: Int, + field224: Int, + field225: Int, + field226: Int, + field227: Int, + field228: Int, + field229: Int, + field230: Int, + field231: Int, + field232: Int, + field233: Int, + field234: Int, + field235: Int, + field236: Int, + field237: Int, + field238: Int, + field239: Int, + field240: Int, + field241: Int, + field242: Int, + field243: Int, + field244: Int, + field245: Int, + field246: Int, + field247: Int, + field248: Int, + field249: Int, + field250: Int, + field251: Int, + field252: Int, + field253: Int, + field254: Int, + field255: Int, + field256: Int, + field257: Int, + field258: Int, + field259: Int, + field260: Int, + field261: Int, + field262: Int, + field263: Int, + field264: Int, + field265: Int, + field266: Int, + field267: Int, + field268: Int, + field269: Int, + field270: Int, + field271: Int, + field272: Int, + field273: Int, + field274: Int, + field275: Int, + field276: Int, + field277: Int, + field278: Int, + field279: Int, + field280: Int, + field281: Int, + field282: Int, + field283: Int, + field284: Int, + field285: Int, + field286: Int, + field287: Int, + field288: Int, + field289: Int, + field290: Int, + field291: Int, + field292: Int, + field293: Int, + field294: Int, + field295: Int, + field296: Int, + field297: Int, + field298: Int, + field299: Int, + field300: Int, + field301: Int, + field302: Int, + field303: Int, + field304: Int, + field305: Int, + field306: Int, + field307: Int, + field308: Int, + field309: Int, + field310: Int, + field311: Int, + field312: Int, + field313: Int, + field314: Int, + field315: Int, + field316: Int, + field317: Int, + field318: Int, + field319: Int, + field320: Int, + field321: Int, + field322: Int, + field323: Int, + field324: Int, + field325: Int, + field326: Int, + field327: Int, + field328: Int, + field329: Int, + field330: Int, + field331: Int, + field332: Int, + field333: Int, + field334: Int, + field335: Int, + field336: Int, + field337: Int, + field338: Int, + field339: Int, + field340: Int, + field341: Int, + field342: Int, + field343: Int, + field344: Int, + field345: Int, + field346: Int, + field347: Int, + field348: Int, + field349: Int, + field350: Int, + field351: Int, + field352: Int, + field353: Int, + field354: Int, + field355: Int, + field356: Int, + field357: Int, + field358: Int, + field359: Int, + field360: Int, + field361: Int, + field362: Int, + field363: Int, + field364: Int, + field365: Int, + field366: Int, + field367: Int, + field368: Int, + field369: Int, + field370: Int, + field371: Int, + field372: Int, + field373: Int, + field374: Int, + field375: Int, + field376: Int, + field377: Int, + field378: Int, + field379: Int, + field380: Int, + field381: Int, + field382: Int, + field383: Int, + field384: Int, + field385: Int, + field386: Int, + field387: Int, + field388: Int, + field389: Int, + field390: Int, + field391: Int, + field392: Int, + field393: Int, + field394: Int, + field395: Int, + field396: Int, + field397: Int, + field398: Int, + field399: Int, + field400: Int, + field401: Int, + field402: Int, + field403: Int, + field404: Int, + field405: Int, + field406: Int, + field407: Int, + field408: Int, + field409: Int, + field410: Int, + field411: Int, + field412: Int, + field413: Int, + field414: Int, + field415: Int, + field416: Int, + field417: Int, + field418: Int, + field419: Int, + field420: Int, + field421: Int, + field422: Int, + field423: Int, + field424: Int, + field425: Int, + field426: Int, + field427: Int, + field428: Int, + field429: Int, + field430: Int, + field431: Int, + field432: Int, + field433: Int, + field434: Int, + field435: Int, + field436: Int, + field437: Int, + field438: Int, + field439: Int, + field440: Int, + field441: Int, + field442: Int, + field443: Int, + field444: Int, + field445: Int, + field446: Int, + field447: Int, + field448: Int, + field449: Int, + field450: Int, + field451: Int, + field452: Int, + field453: Int, + field454: Int, + field455: Int, + field456: Int, + field457: Int, + field458: Int, + field459: Int, + field460: Int, + field461: Int, + field462: Int, + field463: Int, + field464: Int, + field465: Int, + field466: Int, + field467: Int, + field468: Int, + field469: Int, + field470: Int, + field471: Int, + field472: Int, + field473: Int, + field474: Int, + field475: Int, + field476: Int, + field477: Int, + field478: Int, + field479: Int, + field480: Int, + field481: Int, + field482: Int, + field483: Int, + field484: Int, + field485: Int, + field486: Int, + field487: Int, + field488: Int, + field489: Int, + field490: Int, + field491: Int, + field492: Int, + field493: Int, + field494: Int, + field495: Int, + field496: Int, + field497: Int, + field498: Int, + field499: Int, + field500: Int +) + +def main() = { + val p1 = Person( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500 +) + println(p1.field500) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/primitive_ref.check b/examples/flat/nooptimized/primitive_ref.check new file mode 100644 index 000000000..62f945751 --- /dev/null +++ b/examples/flat/nooptimized/primitive_ref.check @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/examples/flat/nooptimized/primitive_ref.effekt b/examples/flat/nooptimized/primitive_ref.effekt new file mode 100644 index 000000000..6aa82602e --- /dev/null +++ b/examples/flat/nooptimized/primitive_ref.effekt @@ -0,0 +1,9 @@ +import ref + +def main() = { + val x = 5 + val y = 6 + val z = ref(x) + z.set(y) + println(z.get()) +} diff --git a/examples/flat/nooptimized/ref_allocate.check b/examples/flat/nooptimized/ref_allocate.check new file mode 100644 index 000000000..c7930257d --- /dev/null +++ b/examples/flat/nooptimized/ref_allocate.check @@ -0,0 +1 @@ +7 \ No newline at end of file diff --git a/examples/flat/nooptimized/ref_allocate.effekt b/examples/flat/nooptimized/ref_allocate.effekt new file mode 100644 index 000000000..2b46ceaa7 --- /dev/null +++ b/examples/flat/nooptimized/ref_allocate.effekt @@ -0,0 +1,19 @@ +import ref + +// md = Person requires 2 saving slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int + ) + +def main() = { + val p1 = ref::allocate() + val p2 = Person(1, 2, 3, 4, 5, 6, 7) + p1.set(p2) + println(p1.get().field7) +} diff --git a/examples/flat/nooptimized/simple_ref.check b/examples/flat/nooptimized/simple_ref.check new file mode 100644 index 000000000..f11c82a4c --- /dev/null +++ b/examples/flat/nooptimized/simple_ref.check @@ -0,0 +1 @@ +9 \ No newline at end of file diff --git a/examples/flat/nooptimized/simple_ref.effekt b/examples/flat/nooptimized/simple_ref.effekt new file mode 100644 index 000000000..3549dea0f --- /dev/null +++ b/examples/flat/nooptimized/simple_ref.effekt @@ -0,0 +1,20 @@ +import ref + +// md = Person requires 2 saving slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int + ) + +def main() = { + val p1 = Person(1, 2, 3, 4, 5, 6, 7) + val p2 = Person(1, 2, 3, 4, 5, 6, 9) + val p3 = ref(p1) + p3.set(p2) + println(p3.get().field7) +} diff --git a/examples/flat/nooptimized/three_md_objects_direct.check b/examples/flat/nooptimized/three_md_objects_direct.check new file mode 100644 index 000000000..8fac22206 --- /dev/null +++ b/examples/flat/nooptimized/three_md_objects_direct.check @@ -0,0 +1,3 @@ +7 +10 +18 \ No newline at end of file diff --git a/examples/flat/nooptimized/three_md_objects_direct.effekt b/examples/flat/nooptimized/three_md_objects_direct.effekt new file mode 100644 index 000000000..ec0561e12 --- /dev/null +++ b/examples/flat/nooptimized/three_md_objects_direct.effekt @@ -0,0 +1,20 @@ +// md = Person requires 2 saving slots +// direct = create person and print field directly +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int + ) + +def main() = { + val p1 = Person(1, 2, 3, 4, 5, 6, 7) + println(p1.field7) + val p2 = Person(8, 9, 10, 11, 12, 13, 14) + val p3 = Person(15, 16, 17, 18, 19, 20, 21) + println(p2.field3) + println(p3.field4) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/trigger_child_freeing.check b/examples/flat/nooptimized/trigger_child_freeing.check new file mode 100644 index 000000000..e69de29bb diff --git a/examples/flat/nooptimized/trigger_child_freeing.effekt b/examples/flat/nooptimized/trigger_child_freeing.effekt new file mode 100644 index 000000000..2f96672f0 --- /dev/null +++ b/examples/flat/nooptimized/trigger_child_freeing.effekt @@ -0,0 +1,64 @@ +// a simple program that creates a more complex object +// -> child1 +// parent +// -> child2 -> child3 +// -> child4 -> child5 -> child6 +// -> child7 -> child8 +// where child1 is OneSlotPerson and child2 and child3 are TwoSlotPerson and child4 and child5 and child6 are ThreeSlotPerson, and child7 and child8 are TwoSlotPerson + +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int +) + +record TwoSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int +) + +record ThreeSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int, + field12: Int, + field13: Int +) + +record Person( + child1: OneSlotPerson, + child2: TwoSlotPerson, + child3: ThreeSlotPerson, + child4: TwoSlotPerson, + child5: OneSlotPerson +) + +def main() = { + var iters = 1 + while(iters <= 66) { + var x = Person( + OneSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5), + TwoSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5, iters + 6), + ThreeSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5, iters + 6, iters + 7, iters + 8, iters + 9, iters + 10, iters + 11, iters + 12), + TwoSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5, iters + 7), + OneSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 6) + ) + iters = iters + 1 + } +} diff --git a/examples/flat/nooptimized/trigger_flush_once.check b/examples/flat/nooptimized/trigger_flush_once.check new file mode 100644 index 000000000..e69de29bb diff --git a/examples/flat/nooptimized/trigger_flush_once.effekt b/examples/flat/nooptimized/trigger_flush_once.effekt new file mode 100644 index 000000000..c1306808c --- /dev/null +++ b/examples/flat/nooptimized/trigger_flush_once.effekt @@ -0,0 +1,17 @@ +// a simple program that triggers flush to-do-list once +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int +) + +def main() = { + var iters = 1 + while(iters <= 65) { + var x = OneSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5) + iters = iters + 1 + } +} diff --git a/examples/flat/nooptimized/trigger_flush_twice.check b/examples/flat/nooptimized/trigger_flush_twice.check new file mode 100644 index 000000000..e69de29bb diff --git a/examples/flat/nooptimized/trigger_flush_twice.effekt b/examples/flat/nooptimized/trigger_flush_twice.effekt new file mode 100644 index 000000000..b364f2fdf --- /dev/null +++ b/examples/flat/nooptimized/trigger_flush_twice.effekt @@ -0,0 +1,17 @@ +// a simple program that triggers flush to-do-list twice +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int +) + +def main() = { + var iters = 1 + while(iters <= 129) { + var x = OneSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5) + iters = iters + 1 + } +} diff --git a/examples/flat/nooptimized/trigger_one_child_freeing.check b/examples/flat/nooptimized/trigger_one_child_freeing.check new file mode 100644 index 000000000..e69de29bb diff --git a/examples/flat/nooptimized/trigger_one_child_freeing.effekt b/examples/flat/nooptimized/trigger_one_child_freeing.effekt new file mode 100644 index 000000000..a44b4896c --- /dev/null +++ b/examples/flat/nooptimized/trigger_one_child_freeing.effekt @@ -0,0 +1,26 @@ +// a simple program that creates a more complex object +// parent -> child1 +// where child1 is OneSlotPerson + +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int +) + +record Person( + child1: OneSlotPerson +) + +def main() = { + var iters = 1 + while(iters <= 65) { + var x = Person( + OneSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5) + ) + iters = iters + 1 + } +} diff --git a/examples/flat/nooptimized/trigger_two_child_freeing.check b/examples/flat/nooptimized/trigger_two_child_freeing.check new file mode 100644 index 000000000..e69de29bb diff --git a/examples/flat/nooptimized/trigger_two_child_freeing.effekt b/examples/flat/nooptimized/trigger_two_child_freeing.effekt new file mode 100644 index 000000000..e8eb31933 --- /dev/null +++ b/examples/flat/nooptimized/trigger_two_child_freeing.effekt @@ -0,0 +1,28 @@ +// a simple program that creates a more complex object +// parent -> child1 +// where child1 is OneSlotPerson + +record OneSlotPerson( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int +) + +record Person( + child1: OneSlotPerson, + child2: OneSlotPerson +) + +def main() = { + var iters = 1 + while(iters <= 64) { + var x = Person( + OneSlotPerson(iters, iters + 1, iters + 2, iters + 3, iters + 4, iters + 5), + OneSlotPerson(iters + 6, iters + 7, iters + 8, iters + 9, iters + 10, iters + 11) + ) + iters = iters + 1 + } +} diff --git a/examples/flat/nooptimized/two_lg_objects.check b/examples/flat/nooptimized/two_lg_objects.check new file mode 100644 index 000000000..8f59f50a4 --- /dev/null +++ b/examples/flat/nooptimized/two_lg_objects.check @@ -0,0 +1,2 @@ +10 +16 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_lg_objects.effekt b/examples/flat/nooptimized/two_lg_objects.effekt new file mode 100644 index 000000000..6393bd171 --- /dev/null +++ b/examples/flat/nooptimized/two_lg_objects.effekt @@ -0,0 +1,20 @@ +// lg = Person fills 2 saving slots completely +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int + ) + +def main() = { + val p1 = Person(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + val p2 = Person(11, 12, 13, 14, 15, 16, 17, 18, 19, 20) + println(p1.field10) + println(p2.field6) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_md_mixed_object.check b/examples/flat/nooptimized/two_md_mixed_object.check new file mode 100644 index 000000000..f21c60d7e --- /dev/null +++ b/examples/flat/nooptimized/two_md_mixed_object.check @@ -0,0 +1,2 @@ +P1Field2 +10 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_md_mixed_object.effekt b/examples/flat/nooptimized/two_md_mixed_object.effekt new file mode 100644 index 000000000..4d67068e4 --- /dev/null +++ b/examples/flat/nooptimized/two_md_mixed_object.effekt @@ -0,0 +1,17 @@ +// md = Person needs 2 slots +// contains strings and integers. +// First slot contains field1, second slot contains field2, field3, field4, field5. +record Person( + field1: Int, + field2: String, + field3: String, + field4: String, + field5: Int + ) + +def main() = { + val p1 = Person(1, "P1Field2", "P1Field3", "P1Field4", 5) + val p2 = Person(6, "P2Field2", "P2Field3", "P2Field4", 10) + println(p1.field2) + println(p2.field5) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_md_objects.check b/examples/flat/nooptimized/two_md_objects.check new file mode 100644 index 000000000..78bd7702c --- /dev/null +++ b/examples/flat/nooptimized/two_md_objects.check @@ -0,0 +1,2 @@ +7 +9 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_md_objects.effekt b/examples/flat/nooptimized/two_md_objects.effekt new file mode 100644 index 000000000..d3bdb013f --- /dev/null +++ b/examples/flat/nooptimized/two_md_objects.effekt @@ -0,0 +1,17 @@ +// md = Person requires 2 saving slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int + ) + +def main() = { + val p1 = Person(1, 2, 3, 4, 5, 6, 7) + val p2 = Person(8, 9, 10, 11, 12, 13, 14) + println(p1.field7) + println(p2.field2) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_sm_mixed_object.check b/examples/flat/nooptimized/two_sm_mixed_object.check new file mode 100644 index 000000000..ca3d17d48 --- /dev/null +++ b/examples/flat/nooptimized/two_sm_mixed_object.check @@ -0,0 +1,2 @@ +P1Field1 +8 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_sm_mixed_object.effekt b/examples/flat/nooptimized/two_sm_mixed_object.effekt new file mode 100644 index 000000000..c07c2af92 --- /dev/null +++ b/examples/flat/nooptimized/two_sm_mixed_object.effekt @@ -0,0 +1,15 @@ +// sm = Person fills 1 saving slot completely +// contains strings and integers +record Person( + field1: String, + field2: Int, + field3: String, + field4: Int + ) + +def main() = { + val p1 = Person("P1Field1", 2, "P1Field3", 4) + val p2 = Person("P2Field1", 6, "P2Field3", 8) + println(p1.field1) + println(p2.field4) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_sm_objects.check b/examples/flat/nooptimized/two_sm_objects.check new file mode 100644 index 000000000..b8a0ddcef --- /dev/null +++ b/examples/flat/nooptimized/two_sm_objects.check @@ -0,0 +1,2 @@ +6 +8 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_sm_objects.effekt b/examples/flat/nooptimized/two_sm_objects.effekt new file mode 100644 index 000000000..a1d1d206c --- /dev/null +++ b/examples/flat/nooptimized/two_sm_objects.effekt @@ -0,0 +1,16 @@ +// sm = Person fills 1 saving slot completely +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int + ) + +def main() = { + val p1 = Person(1, 2, 3, 4, 5, 6) + val p2 = Person(7, 8, 9, 10, 11, 12) + println(p1.field6) + println(p2.field2) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xl_objects.check b/examples/flat/nooptimized/two_xl_objects.check new file mode 100644 index 000000000..10afbfb7e --- /dev/null +++ b/examples/flat/nooptimized/two_xl_objects.check @@ -0,0 +1,2 @@ +11 +18 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xl_objects.effekt b/examples/flat/nooptimized/two_xl_objects.effekt new file mode 100644 index 000000000..e5628b0b7 --- /dev/null +++ b/examples/flat/nooptimized/two_xl_objects.effekt @@ -0,0 +1,21 @@ +// xl = Person needs 3 saving slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int + ) + +def main() = { + val p1 = Person(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) + val p2 = Person(12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22) + println(p1.field11) + println(p2.field7) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xs_objects.check b/examples/flat/nooptimized/two_xs_objects.check new file mode 100644 index 000000000..69cc3abe5 --- /dev/null +++ b/examples/flat/nooptimized/two_xs_objects.check @@ -0,0 +1,2 @@ +3 +5 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xs_objects.effekt b/examples/flat/nooptimized/two_xs_objects.effekt new file mode 100644 index 000000000..02f18b3a9 --- /dev/null +++ b/examples/flat/nooptimized/two_xs_objects.effekt @@ -0,0 +1,13 @@ +// xs = Person fits easily in 1 saving slot +record Person( + field1: Int, + field2: Int, + field3: Int + ) + +def main() = { + val p1 = Person(1, 2, 3) + val p2 = Person(4, 5, 6) + println(p1.field3) + println(p2.field2) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xxl_object_all_fields.check b/examples/flat/nooptimized/two_xxl_object_all_fields.check new file mode 100644 index 000000000..6a0bcb871 --- /dev/null +++ b/examples/flat/nooptimized/two_xxl_object_all_fields.check @@ -0,0 +1,100 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xxl_object_all_fields.effekt b/examples/flat/nooptimized/two_xxl_object_all_fields.effekt new file mode 100644 index 000000000..824a4b603 --- /dev/null +++ b/examples/flat/nooptimized/two_xxl_object_all_fields.effekt @@ -0,0 +1,308 @@ +// xxl: Person has 100 fields -> need x slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int, + field12: Int, + field13: Int, + field14: Int, + field15: Int, + field16: Int, + field17: Int, + field18: Int, + field19: Int, + field20: Int, + field21: Int, + field22: Int, + field23: Int, + field24: Int, + field25: Int, + field26: Int, + field27: Int, + field28: Int, + field29: Int, + field30: Int, + field31: Int, + field32: Int, + field33: Int, + field34: Int, + field35: Int, + field36: Int, + field37: Int, + field38: Int, + field39: Int, + field40: Int, + field41: Int, + field42: Int, + field43: Int, + field44: Int, + field45: Int, + field46: Int, + field47: Int, + field48: Int, + field49: Int, + field50: Int, + field51: Int, + field52: Int, + field53: Int, + field54: Int, + field55: Int, + field56: Int, + field57: Int, + field58: Int, + field59: Int, + field60: Int, + field61: Int, + field62: Int, + field63: Int, + field64: Int, + field65: Int, + field66: Int, + field67: Int, + field68: Int, + field69: Int, + field70: Int, + field71: Int, + field72: Int, + field73: Int, + field74: Int, + field75: Int, + field76: Int, + field77: Int, + field78: Int, + field79: Int, + field80: Int, + field81: Int, + field82: Int, + field83: Int, + field84: Int, + field85: Int, + field86: Int, + field87: Int, + field88: Int, + field89: Int, + field90: Int, + field91: Int, + field92: Int, + field93: Int, + field94: Int, + field95: Int, + field96: Int, + field97: Int, + field98: Int, + field99: Int, + field100: Int +) + +def main() = { + val p1 = Person( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100 +) + println(p1.field1) + println(p1.field2) + println(p1.field3) + println(p1.field4) + println(p1.field5) + println(p1.field6) + println(p1.field7) + println(p1.field8) + println(p1.field9) + println(p1.field10) + println(p1.field11) + println(p1.field12) + println(p1.field13) + println(p1.field14) + println(p1.field15) + println(p1.field16) + println(p1.field17) + println(p1.field18) + println(p1.field19) + println(p1.field20) + println(p1.field21) + println(p1.field22) + println(p1.field23) + println(p1.field24) + println(p1.field25) + println(p1.field26) + println(p1.field27) + println(p1.field28) + println(p1.field29) + println(p1.field30) + println(p1.field31) + println(p1.field32) + println(p1.field33) + println(p1.field34) + println(p1.field35) + println(p1.field36) + println(p1.field37) + println(p1.field38) + println(p1.field39) + println(p1.field40) + println(p1.field41) + println(p1.field42) + println(p1.field43) + println(p1.field44) + println(p1.field45) + println(p1.field46) + println(p1.field47) + println(p1.field48) + println(p1.field49) + println(p1.field50) + println(p1.field51) + println(p1.field52) + println(p1.field53) + println(p1.field54) + println(p1.field55) + println(p1.field56) + println(p1.field57) + println(p1.field58) + println(p1.field59) + println(p1.field60) + println(p1.field61) + println(p1.field62) + println(p1.field63) + println(p1.field64) + println(p1.field65) + println(p1.field66) + println(p1.field67) + println(p1.field68) + println(p1.field69) + println(p1.field70) + println(p1.field71) + println(p1.field72) + println(p1.field73) + println(p1.field74) + println(p1.field75) + println(p1.field76) + println(p1.field77) + println(p1.field78) + println(p1.field79) + println(p1.field80) + println(p1.field81) + println(p1.field82) + println(p1.field83) + println(p1.field84) + println(p1.field85) + println(p1.field86) + println(p1.field87) + println(p1.field88) + println(p1.field89) + println(p1.field90) + println(p1.field91) + println(p1.field92) + println(p1.field93) + println(p1.field94) + println(p1.field95) + println(p1.field96) + println(p1.field97) + println(p1.field98) + println(p1.field99) + println(p1.field100) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xxl_objects.check b/examples/flat/nooptimized/two_xxl_objects.check new file mode 100644 index 000000000..2a817d143 --- /dev/null +++ b/examples/flat/nooptimized/two_xxl_objects.check @@ -0,0 +1,2 @@ +100 +151 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xxl_objects.effekt b/examples/flat/nooptimized/two_xxl_objects.effekt new file mode 100644 index 000000000..7258d179a --- /dev/null +++ b/examples/flat/nooptimized/two_xxl_objects.effekt @@ -0,0 +1,312 @@ +// xxl: Person has 100 fields -> need x slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int, + field12: Int, + field13: Int, + field14: Int, + field15: Int, + field16: Int, + field17: Int, + field18: Int, + field19: Int, + field20: Int, + field21: Int, + field22: Int, + field23: Int, + field24: Int, + field25: Int, + field26: Int, + field27: Int, + field28: Int, + field29: Int, + field30: Int, + field31: Int, + field32: Int, + field33: Int, + field34: Int, + field35: Int, + field36: Int, + field37: Int, + field38: Int, + field39: Int, + field40: Int, + field41: Int, + field42: Int, + field43: Int, + field44: Int, + field45: Int, + field46: Int, + field47: Int, + field48: Int, + field49: Int, + field50: Int, + field51: Int, + field52: Int, + field53: Int, + field54: Int, + field55: Int, + field56: Int, + field57: Int, + field58: Int, + field59: Int, + field60: Int, + field61: Int, + field62: Int, + field63: Int, + field64: Int, + field65: Int, + field66: Int, + field67: Int, + field68: Int, + field69: Int, + field70: Int, + field71: Int, + field72: Int, + field73: Int, + field74: Int, + field75: Int, + field76: Int, + field77: Int, + field78: Int, + field79: Int, + field80: Int, + field81: Int, + field82: Int, + field83: Int, + field84: Int, + field85: Int, + field86: Int, + field87: Int, + field88: Int, + field89: Int, + field90: Int, + field91: Int, + field92: Int, + field93: Int, + field94: Int, + field95: Int, + field96: Int, + field97: Int, + field98: Int, + field99: Int, + field100: Int +) + +def main() = { + val p1 = Person( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100 +) + val p2 = Person( + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200 +) + println(p1.field100) + println(p2.field51) +} \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xxxl_objects.check b/examples/flat/nooptimized/two_xxxl_objects.check new file mode 100644 index 000000000..f10f03bb2 --- /dev/null +++ b/examples/flat/nooptimized/two_xxxl_objects.check @@ -0,0 +1,2 @@ +500 +999 \ No newline at end of file diff --git a/examples/flat/nooptimized/two_xxxl_objects.effekt b/examples/flat/nooptimized/two_xxxl_objects.effekt new file mode 100644 index 000000000..0e3ee0511 --- /dev/null +++ b/examples/flat/nooptimized/two_xxxl_objects.effekt @@ -0,0 +1,1512 @@ +// xxxl: Person has 500 fields -> need x slots +record Person( + field1: Int, + field2: Int, + field3: Int, + field4: Int, + field5: Int, + field6: Int, + field7: Int, + field8: Int, + field9: Int, + field10: Int, + field11: Int, + field12: Int, + field13: Int, + field14: Int, + field15: Int, + field16: Int, + field17: Int, + field18: Int, + field19: Int, + field20: Int, + field21: Int, + field22: Int, + field23: Int, + field24: Int, + field25: Int, + field26: Int, + field27: Int, + field28: Int, + field29: Int, + field30: Int, + field31: Int, + field32: Int, + field33: Int, + field34: Int, + field35: Int, + field36: Int, + field37: Int, + field38: Int, + field39: Int, + field40: Int, + field41: Int, + field42: Int, + field43: Int, + field44: Int, + field45: Int, + field46: Int, + field47: Int, + field48: Int, + field49: Int, + field50: Int, + field51: Int, + field52: Int, + field53: Int, + field54: Int, + field55: Int, + field56: Int, + field57: Int, + field58: Int, + field59: Int, + field60: Int, + field61: Int, + field62: Int, + field63: Int, + field64: Int, + field65: Int, + field66: Int, + field67: Int, + field68: Int, + field69: Int, + field70: Int, + field71: Int, + field72: Int, + field73: Int, + field74: Int, + field75: Int, + field76: Int, + field77: Int, + field78: Int, + field79: Int, + field80: Int, + field81: Int, + field82: Int, + field83: Int, + field84: Int, + field85: Int, + field86: Int, + field87: Int, + field88: Int, + field89: Int, + field90: Int, + field91: Int, + field92: Int, + field93: Int, + field94: Int, + field95: Int, + field96: Int, + field97: Int, + field98: Int, + field99: Int, + field100: Int, + field101: Int, + field102: Int, + field103: Int, + field104: Int, + field105: Int, + field106: Int, + field107: Int, + field108: Int, + field109: Int, + field110: Int, + field111: Int, + field112: Int, + field113: Int, + field114: Int, + field115: Int, + field116: Int, + field117: Int, + field118: Int, + field119: Int, + field120: Int, + field121: Int, + field122: Int, + field123: Int, + field124: Int, + field125: Int, + field126: Int, + field127: Int, + field128: Int, + field129: Int, + field130: Int, + field131: Int, + field132: Int, + field133: Int, + field134: Int, + field135: Int, + field136: Int, + field137: Int, + field138: Int, + field139: Int, + field140: Int, + field141: Int, + field142: Int, + field143: Int, + field144: Int, + field145: Int, + field146: Int, + field147: Int, + field148: Int, + field149: Int, + field150: Int, + field151: Int, + field152: Int, + field153: Int, + field154: Int, + field155: Int, + field156: Int, + field157: Int, + field158: Int, + field159: Int, + field160: Int, + field161: Int, + field162: Int, + field163: Int, + field164: Int, + field165: Int, + field166: Int, + field167: Int, + field168: Int, + field169: Int, + field170: Int, + field171: Int, + field172: Int, + field173: Int, + field174: Int, + field175: Int, + field176: Int, + field177: Int, + field178: Int, + field179: Int, + field180: Int, + field181: Int, + field182: Int, + field183: Int, + field184: Int, + field185: Int, + field186: Int, + field187: Int, + field188: Int, + field189: Int, + field190: Int, + field191: Int, + field192: Int, + field193: Int, + field194: Int, + field195: Int, + field196: Int, + field197: Int, + field198: Int, + field199: Int, + field200: Int, + field201: Int, + field202: Int, + field203: Int, + field204: Int, + field205: Int, + field206: Int, + field207: Int, + field208: Int, + field209: Int, + field210: Int, + field211: Int, + field212: Int, + field213: Int, + field214: Int, + field215: Int, + field216: Int, + field217: Int, + field218: Int, + field219: Int, + field220: Int, + field221: Int, + field222: Int, + field223: Int, + field224: Int, + field225: Int, + field226: Int, + field227: Int, + field228: Int, + field229: Int, + field230: Int, + field231: Int, + field232: Int, + field233: Int, + field234: Int, + field235: Int, + field236: Int, + field237: Int, + field238: Int, + field239: Int, + field240: Int, + field241: Int, + field242: Int, + field243: Int, + field244: Int, + field245: Int, + field246: Int, + field247: Int, + field248: Int, + field249: Int, + field250: Int, + field251: Int, + field252: Int, + field253: Int, + field254: Int, + field255: Int, + field256: Int, + field257: Int, + field258: Int, + field259: Int, + field260: Int, + field261: Int, + field262: Int, + field263: Int, + field264: Int, + field265: Int, + field266: Int, + field267: Int, + field268: Int, + field269: Int, + field270: Int, + field271: Int, + field272: Int, + field273: Int, + field274: Int, + field275: Int, + field276: Int, + field277: Int, + field278: Int, + field279: Int, + field280: Int, + field281: Int, + field282: Int, + field283: Int, + field284: Int, + field285: Int, + field286: Int, + field287: Int, + field288: Int, + field289: Int, + field290: Int, + field291: Int, + field292: Int, + field293: Int, + field294: Int, + field295: Int, + field296: Int, + field297: Int, + field298: Int, + field299: Int, + field300: Int, + field301: Int, + field302: Int, + field303: Int, + field304: Int, + field305: Int, + field306: Int, + field307: Int, + field308: Int, + field309: Int, + field310: Int, + field311: Int, + field312: Int, + field313: Int, + field314: Int, + field315: Int, + field316: Int, + field317: Int, + field318: Int, + field319: Int, + field320: Int, + field321: Int, + field322: Int, + field323: Int, + field324: Int, + field325: Int, + field326: Int, + field327: Int, + field328: Int, + field329: Int, + field330: Int, + field331: Int, + field332: Int, + field333: Int, + field334: Int, + field335: Int, + field336: Int, + field337: Int, + field338: Int, + field339: Int, + field340: Int, + field341: Int, + field342: Int, + field343: Int, + field344: Int, + field345: Int, + field346: Int, + field347: Int, + field348: Int, + field349: Int, + field350: Int, + field351: Int, + field352: Int, + field353: Int, + field354: Int, + field355: Int, + field356: Int, + field357: Int, + field358: Int, + field359: Int, + field360: Int, + field361: Int, + field362: Int, + field363: Int, + field364: Int, + field365: Int, + field366: Int, + field367: Int, + field368: Int, + field369: Int, + field370: Int, + field371: Int, + field372: Int, + field373: Int, + field374: Int, + field375: Int, + field376: Int, + field377: Int, + field378: Int, + field379: Int, + field380: Int, + field381: Int, + field382: Int, + field383: Int, + field384: Int, + field385: Int, + field386: Int, + field387: Int, + field388: Int, + field389: Int, + field390: Int, + field391: Int, + field392: Int, + field393: Int, + field394: Int, + field395: Int, + field396: Int, + field397: Int, + field398: Int, + field399: Int, + field400: Int, + field401: Int, + field402: Int, + field403: Int, + field404: Int, + field405: Int, + field406: Int, + field407: Int, + field408: Int, + field409: Int, + field410: Int, + field411: Int, + field412: Int, + field413: Int, + field414: Int, + field415: Int, + field416: Int, + field417: Int, + field418: Int, + field419: Int, + field420: Int, + field421: Int, + field422: Int, + field423: Int, + field424: Int, + field425: Int, + field426: Int, + field427: Int, + field428: Int, + field429: Int, + field430: Int, + field431: Int, + field432: Int, + field433: Int, + field434: Int, + field435: Int, + field436: Int, + field437: Int, + field438: Int, + field439: Int, + field440: Int, + field441: Int, + field442: Int, + field443: Int, + field444: Int, + field445: Int, + field446: Int, + field447: Int, + field448: Int, + field449: Int, + field450: Int, + field451: Int, + field452: Int, + field453: Int, + field454: Int, + field455: Int, + field456: Int, + field457: Int, + field458: Int, + field459: Int, + field460: Int, + field461: Int, + field462: Int, + field463: Int, + field464: Int, + field465: Int, + field466: Int, + field467: Int, + field468: Int, + field469: Int, + field470: Int, + field471: Int, + field472: Int, + field473: Int, + field474: Int, + field475: Int, + field476: Int, + field477: Int, + field478: Int, + field479: Int, + field480: Int, + field481: Int, + field482: Int, + field483: Int, + field484: Int, + field485: Int, + field486: Int, + field487: Int, + field488: Int, + field489: Int, + field490: Int, + field491: Int, + field492: Int, + field493: Int, + field494: Int, + field495: Int, + field496: Int, + field497: Int, + field498: Int, + field499: Int, + field500: Int +) + +def main() = { + val p1 = Person( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500 +) + val p2 = Person( + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999, + 1000 +) + println(p1.field500) + println(p2.field499) +} \ No newline at end of file diff --git a/examples/neg/issue1165a.check b/examples/neg/issue1165a.check new file mode 100644 index 000000000..e7504117b --- /dev/null +++ b/examples/neg/issue1165a.check @@ -0,0 +1,3 @@ +[error] examples/neg/issue1165a.effekt:5:11: Computation toString is used in an expression position, which requires boxing (e.g. `box toString`) + println(toString) + ^^^^^^^^ \ No newline at end of file diff --git a/examples/neg/issue1165a.effekt b/examples/neg/issue1165a.effekt new file mode 100644 index 000000000..30076acba --- /dev/null +++ b/examples/neg/issue1165a.effekt @@ -0,0 +1,6 @@ +module issue1165a + +def toString(): String = "" +def main() = { + println(toString) +} \ No newline at end of file diff --git a/examples/neg/issue1165b.check b/examples/neg/issue1165b.check new file mode 100644 index 000000000..0ac9422a2 --- /dev/null +++ b/examples/neg/issue1165b.check @@ -0,0 +1,3 @@ +[error] examples/neg/issue1165b.effekt:5:3: Computation e is used in an expression position, which requires boxing (e.g. `box e`) + e + ^ \ No newline at end of file diff --git a/examples/neg/issue1165b.effekt b/examples/neg/issue1165b.effekt new file mode 100644 index 000000000..f7cc726eb --- /dev/null +++ b/examples/neg/issue1165b.effekt @@ -0,0 +1,6 @@ +module issue1165b + +effect exc(): Nothing +def foo() = try { + e +} with e: exc { <> } \ No newline at end of file diff --git a/libraries/common/array.effekt b/libraries/common/array.effekt index 57c621a19..f96590cb8 100644 --- a/libraries/common/array.effekt +++ b/libraries/common/array.effekt @@ -20,10 +20,15 @@ extern type Array[T] extern llvm """ declare noalias ptr @calloc(i64, i64) -define void @array_erase_fields(ptr %array_pointer) { +define void @array_erase(%Object %object) { entry: - %data_pointer = getelementptr inbounds i64, ptr %array_pointer, i64 1 - %size = load i64, ptr %array_pointer, align 8 + ; header of arrays looks like that: rc (0), eraser (1), size (2), data (3) + %size_pointer = getelementptr inbounds i64, ptr %object, i64 2 + %size = load i64, ptr %size_pointer, align 8 + + ; data starts after 3 entries in our object + %data_pointer = getelementptr inbounds ptr, ptr %object, i64 3 + %size_eq_0 = icmp eq i64 %size, 0 br i1 %size_eq_0, label %exit, label %loop loop: @@ -32,11 +37,13 @@ loop: %element_pointer = getelementptr inbounds %Pos, ptr %data_pointer, i64 %loop_phi %element = load %Pos, ptr %element_pointer - call void @erasePositive(%Pos %element) + call void @erasePositive(%Pos %element) ; we erase each child of the array + %inc = add nuw i64 %loop_phi, 1 %cmp = icmp ult i64 %inc, %size br i1 %cmp, label %loop, label %exit exit: + call void @free(%Object %object) ; we delete the array ret void } """ @@ -53,7 +60,7 @@ extern def allocate[T](size: Int) at global: Array[T] = %eraser_pointer = getelementptr ptr, ptr %calloc, i64 1 %size_pointer = getelementptr ptr, ptr %calloc, i64 2 store i64 0, ptr %calloc - store ptr @array_erase_fields, ptr %eraser_pointer + store ptr @array_erase, ptr %eraser_pointer store i64 ${size}, ptr %size_pointer %ret_pos = insertvalue %Pos { i64 0, ptr poison }, ptr %calloc, 1 ret %Pos %ret_pos diff --git a/libraries/common/ref.effekt b/libraries/common/ref.effekt index b206a02b8..5ffff0e1f 100644 --- a/libraries/common/ref.effekt +++ b/libraries/common/ref.effekt @@ -10,10 +10,23 @@ extern js """ """ extern llvm """ -define void @c_ref_erase_field(ptr %0) { - %field = load %Pos, ptr %0, align 8 - tail call void @erasePositive(%Pos %field) - ret void +define void @c_ref_erase(%Object %object) { + + entry: + %objectReferenceCount = getelementptr %Header, %Object %object, i64 0, i32 0 + %referenceCount = load %ReferenceCount, ptr %objectReferenceCount, !noalias !24, !alias.scope !14 + switch %ReferenceCount %referenceCount, label %eraseChildren [i64 0, label %release] + + release: + call ccc void @release(%Object %object) + ret void + + eraseChildren: + %headerSize = ptrtoint ptr getelementptr (%Header, ptr null, i64 1) to i64 + %environment = getelementptr i8, ptr %object, i64 %headerSize + %field = load %Pos, ptr %environment, align 8 + call void @erasePositive(%Pos %field) + ret void } """ @@ -35,13 +48,14 @@ extern def allocate[T]() at global: Ref[T] = chez "(box #f)" llvm """ ; sizeof Header + sizeof Pos = 32 - %ref = tail call noalias ptr @malloc(i64 noundef 32) + %ref = tail call noalias ptr @acquire() + %refEraser = getelementptr ptr, ptr %ref, i64 1 %fieldTag = getelementptr ptr, ptr %ref, i64 2 %fieldData_pointer = getelementptr ptr, ptr %ref, i64 3 store i64 0, ptr %ref, align 8 - store ptr @c_ref_erase_field, ptr %refEraser, align 8 + store ptr @c_ref_erase, ptr %refEraser, align 8 store i64 0, ptr %fieldTag, align 8 store ptr null, ptr %fieldData_pointer, align 8 @@ -57,12 +71,12 @@ extern def ref[T](init: T) at global: Ref[T] = %initTag = extractvalue %Pos ${init}, 0 %initObject_pointer = extractvalue %Pos ${init}, 1 ; sizeof Header + sizeof Pos = 32 - %ref = tail call noalias ptr @malloc(i64 noundef 32) + %ref = tail call noalias ptr @acquire() %refEraser = getelementptr ptr, ptr %ref, i64 1 %refField = getelementptr ptr, ptr %ref, i64 2 store i64 0, ptr %ref, align 8 - store ptr @c_ref_erase_field, ptr %refEraser, align 8 + store ptr @c_ref_erase, ptr %refEraser, align 8 store %Pos ${init}, ptr %refField, align 8 %refWrap = insertvalue %Pos { i64 0, ptr poison }, ptr %ref, 1 diff --git a/libraries/llvm/bytearray.c b/libraries/llvm/bytearray.c index 175099457..a0585332f 100644 --- a/libraries/llvm/bytearray.c +++ b/libraries/llvm/bytearray.c @@ -2,6 +2,7 @@ #define EFFEKT_BYTEARRAY_C #include // For memcopy +#include /** We represent bytearrays like positive types. * @@ -16,10 +17,13 @@ */ -void c_bytearray_erase_noop(void *envPtr) { (void)envPtr; } +void c_bytearray_erase_noop(void* object) { + free(object); +} struct Pos c_bytearray_new(const Int size) { - void *objPtr = malloc(sizeof(struct Header) + size); + int object_size = sizeof(struct Header) + size; + void *objPtr = malloc(object_size); struct Header *headerPtr = objPtr; *headerPtr = (struct Header) { .rc = 0, .eraser = c_bytearray_erase_noop, }; return (struct Pos) { diff --git a/libraries/llvm/io.c b/libraries/llvm/io.c index 3e5d045d1..010a57154 100644 --- a/libraries/llvm/io.c +++ b/libraries/llvm/io.c @@ -597,9 +597,10 @@ typedef struct { } payload; } Promise; -void c_promise_erase_listeners(void *envPtr) { - // envPtr points to a Promise _after_ the eraser, so let's adjust it to point to the promise. - Promise *promise = (Promise*) (envPtr - offsetof(Promise, state)); +void c_promise_erase_listeners(void *object) { + // object points to the Promise object (at rc) + // The environment starts at state (after rc and eraser) + Promise *promise = (Promise*) object; promise_state_t state = promise->state; Stack head; @@ -628,6 +629,7 @@ void c_promise_erase_listeners(void *envPtr) { erasePositive(promise->payload.value); break; } + free(promise); // Free the promise object itself } void c_promise_resume_listeners(Listeners* listeners, struct Pos value) { diff --git a/libraries/llvm/rts.ll b/libraries/llvm/rts.ll index 604d75a25..737b8e08e 100644 --- a/libraries/llvm/rts.ll +++ b/libraries/llvm/rts.ll @@ -93,7 +93,6 @@ %String = type %Pos ; Foreign imports - declare ptr @malloc(i64) declare void @free(ptr) declare ptr @realloc(ptr, i64) @@ -118,6 +117,93 @@ declare void @exit(i64) declare void @llvm.assume(i1) +; typedef struct Slot +; { +; struct Slot* next; +; void (*eraser)(void *object); +; } Slot; +%struct.Slot = type { %struct.Slot*, %Eraser } + +; initializes the todoList with a sentinel slot. +; Sentinel Slot: Fakes a block with a RC=1. It is used to mark the end of the To-Do-List. +; But it is not a real heap-object, because it is not 8-byte aligned. +@todoList = dso_local unnamed_addr global %struct.Slot* inttoptr (i64 1 to %struct.Slot*), align 8 +@nextUnusedSlot = dso_local unnamed_addr global i8* null, align 8 ; Pointer to the next unused Slot + +@slotSize = constant i8 64, align 8 ; The size of each chunk (64 bytes) +@totalAllocationSize = constant i64 4294967296, align 8 ; How much storage do we allocate at the beginning of a program? =4GB + +; Initializes the memory for our effekt-objects that are created by newObject and deleted by eraseObject. +define private void @initializeMemory() nounwind { +entry: + ; we use mmap to allocate memory from the OS. + %size = load i64, i64* @totalAllocationSize, align 8 + + %startAddress = call noalias ptr @malloc(i64 %size) + + store i8* %startAddress, i8** @nextUnusedSlot + ret void +} + + +define private %struct.Slot* @acquire() nounwind { +entry: + ; Load todoList head + %head = load %struct.Slot*, %struct.Slot** @todoList, align 8 + + %isSentinel = icmp eq %struct.Slot* %head, inttoptr (i64 1 to %struct.Slot*) + br i1 %isSentinel, label %bump_alloc, label %reuse + +reuse: + ; Pop from todoList + ; Slot* reusedSlot = todoList; + ; todoList = reusedSlot->next; + %nextptr = getelementptr inbounds %struct.Slot, %struct.Slot* %head, i32 0, i32 0 + %next = load %struct.Slot*, %struct.Slot** %nextptr, align 8 + store %struct.Slot* %next, %struct.Slot** @todoList, align 8 + + ; Call eraser + ; reusedSlot->eraser(reusedSlot); + %eraserptr = getelementptr inbounds %struct.Slot, %struct.Slot* %head, i32 0, i32 1 + %eraser = load %Eraser, void (%struct.Slot*)** %eraserptr, align 8, !alias.scope !14, !noalias !24 + tail call void %eraser(%struct.Slot* %head) + + ; return reusedSlot; + ret %struct.Slot* %head + +bump_alloc: + ; Load raw pointer + %rawBump = load i8*, i8** @nextUnusedSlot, align 8 + + ; Treat it as Object* + %slot = bitcast i8* %rawBump to %struct.Slot* + + ; Move bump pointer forward by object size + %sizeBump = load i8, i8* @slotSize, align 8 + %nextBump = getelementptr i8, i8* %rawBump, i8 %sizeBump + store i8* %nextBump, i8** @nextUnusedSlot, align 8 + + ret %struct.Slot* %slot +} + +; Pushes a slot on the top of the To-Do-List. +define private void @release(%struct.Slot* %slot) nounwind { +entry: + ; oldHead = todoList + %oldHead = load %struct.Slot*, %struct.Slot** @todoList, align 8 + + ; ptr->next = oldHead + %nextPtr = getelementptr %struct.Slot, %struct.Slot* %slot, i32 0, i32 0 + store %struct.Slot* %oldHead, %struct.Slot** %nextPtr, align 8 + + ; todoList = ptr + store %struct.Slot* %slot, %struct.Slot** @todoList, align 8 + + ret void +} + + + ; Prompts define private %Prompt @currentPrompt(%Stack %stack) { @@ -133,12 +219,8 @@ define private %Prompt @freshPrompt() { ret %Prompt %prompt } -; Garbage collection - define private %Object @newObject(%Eraser %eraser, i64 %environmentSize) alwaysinline { - %headerSize = ptrtoint ptr getelementptr (%Header, ptr null, i64 1) to i64 - %size = add i64 %environmentSize, %headerSize - %object = call ptr @malloc(i64 %size) + %object = call ptr @acquire() %objectReferenceCount = getelementptr %Header, ptr %object, i64 0, i32 0 %objectEraser = getelementptr %Header, ptr %object, i64 0, i32 1 store %ReferenceCount 0, ptr %objectReferenceCount, !alias.scope !14, !noalias !24 @@ -196,9 +278,7 @@ define private void @eraseObject(%Object %object) alwaysinline { free: %objectEraser = getelementptr %Header, ptr %object, i64 0, i32 1 %eraser = load %Eraser, ptr %objectEraser, !alias.scope !14, !noalias !24 - %environment = call %Environment @objectEnvironment(%Object %object) - call void %eraser(%Environment %environment) - call void @free(%Object %object) + call void %eraser(%Object %object) br label %done done: @@ -456,7 +536,7 @@ decrement: ret void free: - call void @free(%Prompt %prompt) + call void @free(%Prompt %prompt) ;df: wird gecalled, obwohl es nie allocated wurde -> gibt warning ret void } @@ -479,7 +559,7 @@ define private %Stack @underflowStack(%Stack %stack) { store %Stack null, ptr %promptStack_pointer, !alias.scope !13, !noalias !23 call void @erasePrompt(%Prompt %prompt) - call void @free(%Stack %stack) + call void @free(%Stack %stack) ;df: wird gecalled, obwohl es nie allocated wurde -> gibt warning ret %Stack %rest }