diff --git a/builtin/Builtin.vix b/builtin/Builtin.vix index 5194cbfc..aa56f88e 100644 --- a/builtin/Builtin.vix +++ b/builtin/Builtin.vix @@ -18,7 +18,11 @@ subInt : Int -> Int -> Int EmptyRepresentation : Type WordRepresentation : Type +PointerRepresentation : Type maxRepresentation : Type -> Type -> Type addRepresentation : Type -> Type -> Type +representationBytes : Type -> Int +representationPointers : Type -> Int +representationNonPointerBytes : Type -> Int diff --git a/rts/Sixten.Builtin.ll b/rts/Sixten.Builtin.ll index 51814714..4d8132f3 100644 --- a/rts/Sixten.Builtin.ll +++ b/rts/Sixten.Builtin.ll @@ -2,10 +2,11 @@ declare void @print_int(i64 %i) declare void @exit(i32) -@Sixten.Builtin.Int = unnamed_addr constant i64 8 -@Sixten.Builtin.Type = unnamed_addr constant i64 8 +@Sixten.Builtin.Int = unnamed_addr constant i64 u0x0000000800000000 +@Sixten.Builtin.Type = unnamed_addr constant i64 u0x0000000800000000 @Sixten.Builtin.EmptyRepresentation = unnamed_addr constant i64 0 -@Sixten.Builtin.WordRepresentation = unnamed_addr constant i64 8 +@Sixten.Builtin.PointerRepresentation = unnamed_addr constant i64 u0x0000000000000008 +@Sixten.Builtin.WordRepresentation = unnamed_addr constant i64 u0x0000000800000000 define external fastcc void @Sixten.Builtin.unknown(ptr %destination, i64 %a) { call void @exit(i32 7411) @@ -18,15 +19,25 @@ define external fastcc i64 @Sixten.Builtin.addRepresentation(i64 %a, i64 %b) { } define external fastcc i64 @Sixten.Builtin.maxRepresentation(i64 %a, i64 %b) { - %a_lt_b = icmp ult i64 %a, %b - %result = select i1 %a_lt_b, i64 %b, i64 %a + %a_ptrs = trunc i64 %a to i32 + %b_ptrs = trunc i64 %b to i32 + %a_non_ptrs64 = lshr i64 %a, 32 + %b_non_ptrs64 = lshr i64 %b, 32 + %a_non_ptrs = trunc i64 %a_non_ptrs64 to i32 + %b_non_ptrs = trunc i64 %b_non_ptrs64 to i32 + %a_ptrs_lt_b_ptrs = icmp ult i32 %a_ptrs, %b_ptrs + %result_ptrs = select i1 %a_ptrs_lt_b_ptrs, i32 %b_ptrs, i32 %a_ptrs + %a_non_ptrs_lt_b_non_ptrs = icmp ult i32 %a_non_ptrs, %b_non_ptrs + %result_non_ptrs = select i1 %a_non_ptrs_lt_b_non_ptrs, i32 %b_non_ptrs, i32 %a_non_ptrs + %result_lower = zext i32 %result_ptrs to i64 + %result_non_ptrs64 = zext i32 %result_non_ptrs to i64 + %result_upper = shl nuw i64 %result_non_ptrs64, 32 + %result = or i64 %result_lower, %result_upper ret i64 %result } -define external fastcc void @Sixten.Builtin.printInt(i64 %tagged_i) { - %i = ashr i64 %tagged_i, 1 +define external fastcc void @Sixten.Builtin.printInt(i64 %i) { call void @print_int(i64 %i) - ret void } define external fastcc i64 @Sixten.Builtin.addInt(i64 %a, i64 %b) { @@ -35,8 +46,7 @@ define external fastcc i64 @Sixten.Builtin.addInt(i64 %a, i64 %b) { } define external fastcc i64 @Sixten.Builtin.mulInt(i64 %a, i64 %b) { - %doubled_result = mul i64 %a, %b - %result = ashr i64 %doubled_result, 1 + %result = mul i64 %a, %b ret i64 %result } @@ -44,3 +54,21 @@ define external fastcc i64 @Sixten.Builtin.subInt(i64 %a, i64 %b) { %result = sub i64 %a, %b ret i64 %result } + +define external fastcc i64 @Sixten.Builtin.representationBytes(i64 %a) { + %ptr_bytes = call fastcc i64 @Sixten.Builtin.representationPointerBytes(i64 %a) + %non_ptr_bytes = call fastcc i64 @Sixten.Builtin.representationNonPointerBytes(i64 %a) + %bytes = add nuw i64 %ptr_bytes, %non_ptr_bytes + ret i64 %bytes +} + +define external fastcc i64 @Sixten.Builtin.representationPointerBytes(i64 %a) { + %ptrs = trunc i64 %a to i32 + %ptrs64 = zext i32 %ptrs to i64 + ret i64 %ptrs64 +} + +define external fastcc i64 @Sixten.Builtin.representationNonPointerBytes(i64 %a) { + %non_ptrs = lshr i64 %b, 32 + ret i64 %non_ptrs +} diff --git a/rts/reference_counting.c b/rts/reference_counting.c index ea842b61..153d92a9 100644 --- a/rts/reference_counting.c +++ b/rts/reference_counting.c @@ -5,6 +5,7 @@ #define unlikely(x) __builtin_expect(!!(x), 0) #define debug_printf(...) // printf(__VA_ARGS__) +<<<<<<< HEAD const uintptr_t INLINE_SIZE_MASK = 0xFF << 3; // heap pointer: | 45 bits pointer data | 8 bits constructor tag | 8 bits word size | 2 bits object type | 1 | @@ -82,6 +83,63 @@ uintptr_t sixten_allocate(uintptr_t constructor_tag, uintptr_t size){ | ((uintptr_t)constructor_tag << 11) | (uintptr_t)inline_size | 1; +======= +// pointer: 48 bits pointer data +// | 16 bits constructor tag +// pointee: 32 bits ref count | +// | 32 bits pointer bytes +// ptr -> | pointer data +// | non-pointer data + +typedef uint32_t ReferenceCount; +typedef uint32_t PointerBytes; +const size_t POINTER_OFFSET = 16; +const uintptr_t CONSTRUCTOR_TAG_MASK = UINTPTR_C(0xffff); + +static +void print_heap_object(uintptr_t heap_object) { + char* data = sixten_heap_object_data(heap_object); + debug_printf("data: 0x%" PRIxPTR, (uintptr_t)data); + uintptr_t constructor_tag = sixten_heap_object_constructor_tag(heap_object); + debug_printf(", constructor_tag: %" PRIuPTR, constructor_tag); + uintptr_t inline_pointers = sixten_heap_object_pointer_bytes(heap_object); + debug_printf(", pointer_bytes: %" PRIuPTR, pointer_bytes); +} + +char* sixten_heap_object_data(uintptr_t word) { + return (char*)((intptr_t)word >> POINTER_OFFSET); +} + +uintptr_t sixten_heap_object_constructor_tag(uintptr_t word) { + return word & CONSTRUCTOR_TAG_MASK; +} + +uintptr_t sixten_heap_object_pointer_bytes(uintptr_t word) { + char* data = sixten_heap_object_data(word); + if (data == 0) { + return 0; + } + return *(PointerBytes*)(data - sizeof(PointerBytes)); +} + +uintptr_t sixten_allocate(uintptr_t constructor_tag, uintptr_t pointer_bytes, uintptr_t non_pointer_bytes){ + debug_printf("heap allocating %" PRIuPTR " bytes \n", bytes); + uintptr_t bytes = pointer_bytes + non_pointer_bytes; + if (bytes == 0) { + return constructor_tag & CONSTRUCTOR_TAG_MASK; + } + bytes += sizeof(ReferenceCount); + bytes += sizeof(PointerBytes); + + char* heap_pointer = mi_malloc(bytes); + char* object_pointer = heap_pointer + sizeof(ReferenceCount) + sizeof(PointerBytes); + *(ReferenceCount*)heap_pointer = 1; + *(PointerBytes*)(heap_pointer + sizeof(ReferenceCount)) = pointer_bytes; + + uintptr_t result + = ((uintptr_t)object_pointer << POINTER_OFFSET) + | (constructor_tag & CONSTRUCTOR_TAG_MASK); +>>>>>>> 6db7d94 (wip) debug_printf("heap allocated object "); print_heap_object(result); diff --git a/rts/reference_counting.h b/rts/reference_counting.h index 67d60d5f..1156e297 100644 --- a/rts/reference_counting.h +++ b/rts/reference_counting.h @@ -2,6 +2,7 @@ #include +<<<<<<< HEAD int sixten_is_heap_object(uintptr_t word); uintptr_t sixten_heap_object_size(uintptr_t word); char* sixten_heap_object_pointer(uintptr_t word); @@ -13,3 +14,14 @@ void sixten_retain(uintptr_t word); void sixten_retains(char* pointer, uintptr_t size); void sixten_release(uintptr_t word); void sixten_releases(char* pointer, uintptr_t size); +======= +char* sixten_heap_object_data(uintptr_t word); +uintptr_t sixten_heap_object_constructor_tag(uintptr_t word); +uintptr_t sixten_heap_object_pointer_bytes(uintptr_t word); + +uintptr_t sixten_allocate(uintptr_t constructor_tag, uintptr_t pointer_bytes, uintptr_t non_pointer_bytes); +void sixten_retain(uintptr_t word); +void sixten_retains(char* pointer, uintptr_t pointer_bytes); +void sixten_release(uintptr_t word); +void sixten_releases(char* pointer, uintptr_t pointer_bytes); +>>>>>>> 6db7d94 (wip) diff --git a/src/Assembly.hs b/src/Assembly.hs index b067718f..1a2a1dae 100644 --- a/src/Assembly.hs +++ b/src/Assembly.hs @@ -26,7 +26,6 @@ data Operand = LocalOperand !Local | GlobalConstant !Name.Lifted !Type | GlobalFunction !Name.Lifted !(Return Type) [Type] - | StructOperand [Operand] | Lit !Literal deriving (Eq, Show, Generic, Hashable) @@ -34,7 +33,6 @@ data Type = Word | WordPointer | FunctionPointer !(Return Type) [Type] - | Struct [Type] deriving (Eq, Show, Generic, Hashable) data Return a = Void | Return a @@ -58,9 +56,14 @@ data Instruction , constructorTag :: !Word8 , size :: !Operand } + | Retains !Operand !Operand + | Releases !Operand !Operand + | AllocateGlobal + { destination :: !Local + , size :: !Operand + } | ExtractHeapPointer !Local !Operand | ExtractHeapPointerConstructorTag !Local !Operand - | ExtractValue !Local !Operand !Int | Switch !(Return (Type, Local)) !Operand [(Integer, BasicBlock)] BasicBlock deriving (Eq, Show, Generic, Hashable) @@ -108,8 +111,6 @@ instance Pretty Operand where "(" <> pretty type_ <+> "constant" <+> pretty global <> ")" GlobalFunction global return_ arity -> "(function " <> pretty return_ <> " (" <> pretty arity <> ")" <+> pretty global <> ")" - StructOperand operands -> - "{" <> hsep (punctuate comma $ pretty <$> operands) <> "}" Lit lit -> pretty lit @@ -119,7 +120,6 @@ instance Pretty Type where Word -> "word" WordPointer -> "word*" FunctionPointer returnType argTypes -> pretty returnType <+> tupled (pretty <$> argTypes) - Struct types -> "{" <> hsep (punctuate comma $ pretty <$> types) <> "}" instance Pretty Instruction where pretty instruction = @@ -151,13 +151,17 @@ instance Pretty Instruction where RestoreStack o -> voidInstr "restorestack" [o] HeapAllocate dst a b -> - returningInstr dst "heap_alloc" [Lit $ Literal.Integer $ fromIntegral a, b] + returningInstr dst "gcmalloc" [Lit $ Literal.Integer $ fromIntegral a, b] + Retains pointer size_ -> + voidInstr "retains" [pointer, size_] + Releases pointer size_ -> + voidInstr "releases" [pointer, size_] + AllocateGlobal dst size_ -> + returningInstr dst "malloc" [size_] ExtractHeapPointer dst a -> returningInstr dst "extract heap pointer" [a] ExtractHeapPointerConstructorTag dst a -> returningInstr dst "extract heap pointer" [a] - ExtractValue dst struct index -> - pretty dst <+> "=" <+> "extractvalue" <+> hsep [pretty struct, pretty index] Switch result scrutinee branches default_ -> case result of Void -> "" diff --git a/src/AssemblyToLLVM.hs b/src/AssemblyToLLVM.hs index 460cd4b6..f21b32f5 100644 --- a/src/AssemblyToLLVM.hs +++ b/src/AssemblyToLLVM.hs @@ -20,7 +20,6 @@ import qualified Data.ByteString.Short as ShortByteString import Data.HashMap.Lazy (HashMap) import qualified Data.HashMap.Lazy as HashMap import qualified Data.HashSet as HashSet -import qualified Data.List as List import Data.String (fromString) import qualified Literal import qualified Name @@ -85,8 +84,6 @@ llvmType type_ = Assembly.Word -> wordSizedInt Assembly.WordPointer -> pointer Assembly.FunctionPointer _returnType _argumentTypes -> pointer - Assembly.Struct types -> - braces $ llvmType <$> types parameterAttributes :: Assembly.Type -> [Builder] parameterAttributes type_ = @@ -94,7 +91,6 @@ parameterAttributes type_ = Assembly.Word -> [] Assembly.WordPointer -> ["nonnull"] Assembly.FunctionPointer {} -> ["nonnull"] - Assembly.Struct _ -> [] llvmReturnType :: Assembly.Return Assembly.Type -> Builder llvmReturnType result = @@ -425,7 +421,7 @@ assembleInstruction instruction = declare "llvm.stackrestore" $ "declare ccc void @llvm.stackrestore" <> parens [pointer] emitInstruction $ "call ccc void @llvm.stackrestore" <> parens [typedOperand argument'] Assembly.HeapAllocate {destination, constructorTag, size} -> do - destination' <- activateLocal Assembly.Word destination + destination' <- activateLocal Assembly.WordPointer destination size' <- assembleOperandAndCastTo Assembly.Word size declare "__regcall3__heap_alloc" @@ -442,6 +438,9 @@ assembleInstruction instruction = [ "i8 " <> Builder.word8Dec constructorTag , typedOperand size' ] + Assembly.Retains ptr size -> _ + Assembly.Releases ptr size -> _ + Assembly.AllocateGlobal dst size -> _ Assembly.ExtractHeapPointer destination pointer_ -> do destination' <- activateLocal Assembly.WordPointer destination pointer' <- assembleOperandAndCastTo Assembly.Word pointer_ @@ -457,14 +456,6 @@ assembleInstruction instruction = <> wordSizedInt <> " @heap_object_constructor_tag" <> parens [typedOperand pointer'] - Assembly.ExtractValue destination struct index -> do - (_nameSuggestion, structType, struct') <- assembleOperand struct - case structType of - Assembly.Struct types -> do - let fieldType = types List.!! index - destination' <- activateLocal fieldType destination - emitInstruction $ localName destination' <> " = extractvalue " <> typedOperand struct' <> ", " <> Builder.intDec index - _ -> panic "AssemblyToLLVM.assembleInstruction: ExtractValue of non-struct" Assembly.Switch destination scrutinee branches (Assembly.BasicBlock defaultBranchInstructions defaultBranchResult) -> do scrutinee' <- assembleOperandAndCastTo Assembly.Word scrutinee branchLabels <- forM branches \(i, _) -> do @@ -534,8 +525,6 @@ assembleOperand = \case emitInstruction $ localName destination <> " = load " <> llvmType_ <> ", ptr " <> globalName globalName_ <> ", align " <> Builder.intDec alignment pure (nameSuggestion, Assembly.WordPointer, TypedOperand {type_ = llvmType_, operand = Local destination}) - Assembly.Struct types -> - pure (nameSuggestion, Assembly.Struct types, TypedOperand {type_ = pointer, operand = Global globalName_}) Assembly.GlobalFunction global returnType parameterTypes -> do let defType = Assembly.FunctionPointer returnType parameterTypes globalNameText = Assembly.nameText global @@ -544,18 +533,6 @@ assembleOperand = \case globalType = llvmType defType declare globalName_ $ "declare fastcc " <> llvmReturnType returnType <> " " <> globalName globalName_ <> parens (llvmType <$> parameterTypes) pure (nameSuggestion, defType, TypedOperand {type_ = globalType, operand = Global globalName_}) - Assembly.StructOperand operands -> do - typedOperands <- mapM assembleOperand operands - let types = (\(_, type', _) -> type') <$> typedOperands - operands' = (\(_, _, operand') -> operand') <$> typedOperands - type_ = Assembly.Struct types - llvmType_ = llvmType type_ - go (index, struct) fieldOperand = do - struct' <- freshName "struct" - emitInstruction $ localName struct' <> " = insertvalue " <> typedOperand struct <> ", " <> typedOperand fieldOperand <> ", " <> Builder.intDec index - pure (index + 1, TypedOperand {type_ = llvmType_, operand = Local struct'}) - result <- snd <$> foldM go (0, TypedOperand {type_ = llvmType_, operand = Constant "undef"}) operands' - pure ("struct", type_, result) Assembly.Lit lit -> case lit of Literal.Integer int -> @@ -586,20 +563,6 @@ cast nameSuggestion newType type_ operand_ emitInstruction $ localName newOperand <> " = ptrtoint " <> typedOperand operand_ <> " to " <> llvmNewType pure TypedOperand {type_ = llvmNewType, operand = Local newOperand} - (Assembly.Struct types, Assembly.Struct newTypes) -> do - let llvmType_ = llvmType type_ - go (index, struct) (fieldType, newFieldType) = do - field <- freshName "field" - let fieldOperand = TypedOperand {type_ = llvmType fieldType, operand = Local field} - emitInstruction $ - localName field <> " = extractvalue " <> typedOperand operand_ <> ", " <> Builder.intDec index - castField <- cast "field" newFieldType fieldType fieldOperand - struct' <- freshName "struct" - emitInstruction $ - localName struct' <> " = insertvalue " <> typedOperand struct <> ", " <> typedOperand castField <> ", " <> Builder.intDec index - pure (index + 1, TypedOperand {type_ = llvmType_, operand = Local struct'}) - - snd <$> foldM go (0, TypedOperand {type_ = llvmType_, operand = Constant "undef"}) (zip types newTypes) _ -> do newOperand <- freshName $ nameSuggestion <> "_cast" emitInstruction $ diff --git a/src/Builtin.hs b/src/Builtin.hs index 3fde1db5..87f22de9 100644 --- a/src/Builtin.hs +++ b/src/Builtin.hs @@ -100,6 +100,10 @@ pattern WordRepresentationName :: Name.Qualified pattern WordRepresentationName = "Sixten.Builtin.WordRepresentation" +pattern PointerRepresentationName :: Name.Qualified +pattern PointerRepresentationName = + "Sixten.Builtin.PointerRepresentation" + pattern AddRepresentationName :: Name.Qualified pattern AddRepresentationName = "Sixten.Builtin.addRepresentation" diff --git a/src/ClosureConverted/Representation.hs b/src/ClosureConverted/Representation.hs index 6eb9c697..35a5bd80 100644 --- a/src/ClosureConverted/Representation.hs +++ b/src/ClosureConverted/Representation.hs @@ -135,7 +135,7 @@ typeRepresentation env type_ = maybeType' <- Evaluation.applyFunction env (Telescope.fromVoid tele) args case maybeType' of Nothing -> - pure Representation.Direct -- a closure + pure Representation.Direct Just type' -> typeRepresentation env type' Syntax.DataDefinition Boxed _ -> @@ -173,8 +173,8 @@ constructorFieldRepresentation env type_ accumulatedRepresentation = do Domain.Pi _ fieldType closure -> do fieldRepresentation <- typeRepresentation env fieldType case accumulatedRepresentation <> fieldRepresentation of - Representation.Indirect -> - pure Representation.Indirect + representation@Representation.Indirect -> + pure representation accumulatedRepresentation' -> do (context', var) <- Environment.extend env type'' <- Evaluation.evaluateClosure closure $ Domain.var var @@ -198,7 +198,7 @@ compileData env dataTypeName (Syntax.ConstructorDefinitions constructors) = do (boxity, maybeTags) <- fetch $ Query.ConstructorRepresentations dataTypeName case boxity of Boxed -> - pure $ Syntax.Global (Name.Lifted Builtin.WordRepresentationName 0) + pure $ Syntax.Global (Name.Lifted Builtin.PointerRepresentationName 0) Unboxed -> do compiledConstructorFields <- forM (OrderedHashMap.toList constructors) \(_, type_) -> do type' <- Evaluation.evaluate env type_ diff --git a/src/ClosureConvertedToAssembly.hs b/src/ClosureConvertedToAssembly.hs index 1f38e88f..4f5f2128 100644 --- a/src/ClosureConvertedToAssembly.hs +++ b/src/ClosureConvertedToAssembly.hs @@ -58,7 +58,7 @@ runBuilder (Builder s) = evalStateT s BuilderState - { fresh = 3 + { fresh = 0 , instructions = mempty } @@ -95,15 +95,14 @@ emptyEnvironment = extend :: Environment v -> Syntax.Type v -> Operand -> Builder (Environment (Succ v)) extend env type_ location = - Builder $ - lift do - type' <- Evaluation.evaluate (Context.toEnvironment env.context) type_ - (context', var) <- Context.extend env.context type' - pure - Environment - { context = context' - , varLocations = EnumMap.insert var location env.varLocations - } + Builder $ lift do + type' <- Evaluation.evaluate (Context.toEnvironment env.context) type_ + (context', var) <- Context.extend env.context type' + pure + Environment + { context = context' + , varLocations = EnumMap.insert var location env.varLocations + } operandNameSuggestion :: Assembly.Operand -> Assembly.NameSuggestion operandNameSuggestion operand = @@ -116,21 +115,18 @@ operandNameSuggestion operand = Assembly.NameSuggestion $ Assembly.nameText global Assembly.Lit _ -> "literal" - Assembly.StructOperand _ -> - "struct" data Operand = Empty | -- | word sized Direct !Assembly.Operand - | Indirect !Assembly.Operand + | Indirect !Assembly.Operand !Assembly.Operand ------------------------------------------------------------------------------- indexOperand :: Index v -> Environment v -> Operand indexOperand index env = do - let var = - Context.lookupIndexVar index env.context + let var = Context.lookupIndexVar index env.context fromMaybe (panic "ClosureConvertedToAssembly.indexOperand") $ EnumMap.lookup var env.varLocations @@ -143,6 +139,7 @@ globalConstantOperand name = do Assembly.GlobalConstant name case representation of Representation.Empty -> Assembly.WordPointer Representation.Direct -> Assembly.Word + -- TODO: needs to be a reference pair Representation.Indirect -> Assembly.WordPointer _ -> panic $ "ClosureConvertedToAssembly.globalConstantLocation: global without constant signature " <> show name @@ -169,6 +166,18 @@ heapAllocate nameSuggestion constructorTag size = do emit Assembly.HeapAllocate {destination, constructorTag, size} pure $ Assembly.LocalOperand destination +retains :: Assembly.Operand -> Assembly.Operand -> Builder () +retains pointer size = emit $ Assembly.Retains pointer size + +releases :: Assembly.Operand -> Assembly.Operand -> Builder () +releases pointer size = emit $ Assembly.Releases pointer size + +allocateGlobal :: Assembly.NameSuggestion -> Assembly.Operand -> Builder Assembly.Operand +allocateGlobal nameSuggestion size = do + destination <- freshLocal nameSuggestion + emit Assembly.AllocateGlobal {destination, size} + pure $ Assembly.LocalOperand destination + extractHeapPointer :: Assembly.NameSuggestion -> Assembly.Operand -> Builder Assembly.Operand extractHeapPointer nameSuggestion location = do destination <- freshLocal nameSuggestion @@ -183,13 +192,12 @@ extractHeapPointerConstructorTag nameSuggestion location = do typeOf :: Environment v -> Syntax.Term v -> Builder (Operand, Representation) typeOf env term = do - (type_, typeRepresentation) <- Builder $ - lift do - value <- Evaluation.evaluate (Context.toEnvironment env.context) term - typeValue <- TypeOf.typeOf env.context value - typeRepresentation <- ClosureConverted.Representation.typeRepresentation (Context.toEnvironment env.context) typeValue - type_ <- Readback.readback (Context.toEnvironment env.context) typeValue - pure (type_, typeRepresentation) + (type_, typeRepresentation) <- Builder $ lift do + value <- Evaluation.evaluate (Context.toEnvironment env.context) term + typeValue <- TypeOf.typeOf env.context value + typeRepresentation <- ClosureConverted.Representation.typeRepresentation (Context.toEnvironment env.context) typeValue + type_ <- Readback.readback (Context.toEnvironment env.context) typeValue + pure (type_, typeRepresentation) typeOperand <- generateType env type_ pure (typeOperand, typeRepresentation) @@ -291,12 +299,6 @@ addPointer nameSuggestion i1 i2 = do emit $ Assembly.AddPointer destination i1 i2 pure $ Assembly.LocalOperand destination -extractValue :: Assembly.NameSuggestion -> Assembly.Operand -> Int -> Builder Assembly.Operand -extractValue nameSuggestion struct index = do - destination <- freshLocal nameSuggestion - emit $ Assembly.ExtractValue destination struct index - pure $ Assembly.LocalOperand destination - ------------------------------------------------------------------------------- forceIndirect :: Operand -> Builder (Assembly.Operand, Builder ()) @@ -371,8 +373,8 @@ generateModuleInit generateModuleInit moduleName definitions = runBuilder do inited <- load "inited" $ Assembly.GlobalConstant initedName Assembly.Word - Assembly.Void <- - switch + void + $ switch Assembly.Void inited [ @@ -386,7 +388,7 @@ generateModuleInit moduleName definitions = pure Assembly.Void ) ] - $ pure Assembly.Void + $ pure Assembly.Void instructions <- gets (.instructions) pure [ @@ -405,12 +407,9 @@ generateModuleInit moduleName definitions = initedName = moduleInitedName moduleName initDefinition (name, definition) = case definition of - Assembly.KnownConstantDefinition {} -> - pure () - Assembly.ConstantDefinition {} -> - callVoid (initDefinitionName name) [] - Assembly.FunctionDefinition {} -> - pure () + Assembly.KnownConstantDefinition {} -> pure () + Assembly.ConstantDefinition {} -> callVoid (initDefinitionName name) [] + Assembly.FunctionDefinition {} -> pure () generateDefinition :: Name.Lifted -> Syntax.Definition -> M (Maybe Assembly.Definition) generateDefinition name@(Name.Lifted qualifiedName _) definition = do @@ -447,21 +446,20 @@ generateGlobal env name representation term = do Nothing -> case representation of Representation.Empty -> makeConstantDefinition Assembly.WordPointer do - (_, deallocateTerm) <- generateTypedTerm env term (Direct emptyTypeOperand) representation - sequence_ deallocateTerm + (_, releaseTerm) <- generateTypedTerm env term (Direct emptyTypeOperand) representation + sequence_ releaseTerm Representation.Direct -> makeConstantDefinition Assembly.Word do - (result, deallocateTerm) <- generateTypedTerm env term (Direct directTypeOperand) representation + (result, releaseTerm) <- generateTypedTerm env term (Direct directTypeOperand) representation directResult <- forceDirect result - sequence_ deallocateTerm + sequence_ releaseTerm initGlobal name Assembly.Word directResult Representation.Indirect -> makeConstantDefinition Assembly.WordPointer do (type_, _representation) <- typeOf env term typeSize <- sizeOfType type_ - taggedPointer <- heapAllocate "tagged_global_pointer" 0 typeSize - pointer <- extractHeapPointer "global_pointer" taggedPointer - storeTerm env term pointer type_ - initGlobal name Assembly.WordPointer pointer + globalPointer <- allocateGlobal "global" typeSize + storeTerm env term globalPointer type_ + initGlobal name Assembly.WordPointer globalPointer makeConstantDefinition :: Assembly.Type @@ -518,7 +516,7 @@ generateFunction env returnRepresentation tele parameterRepresentations params = makeFunctionDefinition (Assembly.Return Assembly.Word) (toList params) do (result, deallocateTerm) <- generateTypedTerm env term (Direct directTypeOperand) returnRepresentation directResult <- forceDirect result - sequence_ deallocateTerm + sequence_ releaseTerm pure $ Assembly.Return directResult Representation.Indirect -> do returnLocation <- freshLocal "return_location" @@ -551,19 +549,23 @@ makeFunctionDefinition makeFunctionDefinition returnType parameters m = do returnOperand <- m instructions <- gets (.instructions) - pure $ Assembly.FunctionDefinition returnType parameters $ Assembly.BasicBlock (toList instructions) returnOperand + pure $ + Assembly.FunctionDefinition + returnType_ + parameters + $ Assembly.BasicBlock (toList instructions) returnOperand ------------------------------------------------------------------------------- generateType :: Environment v -> Syntax.Type v -> Builder Operand generateType env type_ = do - (type', maybeDeallocateType) <- generateTypedTerm env type_ (Direct pointerBytesOperand) Representation.Direct - case maybeDeallocateType of + (type', maybeReleaseType) <- generateTypedTerm env type_ (Direct pointerBytesOperand) Representation.Direct + case maybeReleaseType of Nothing -> pure type' - Just deallocateType -> do + Just releaseType -> do directType <- forceDirect type' - deallocateType + releaseType pure $ Direct directType generateTypedTerm :: Environment v -> Syntax.Term v -> Operand -> Representation -> Builder (Operand, Maybe (Builder ())) @@ -572,10 +574,13 @@ generateTypedTerm env term type_ representation = do typeSize <- sizeOfType type_ stack <- saveStack termLocation <- stackAllocate "term_location" typeSize + let release = releases termLocation typeSize storeTerm env term termLocation type_ pure ( Indirect termLocation - , Just $ restoreStack stack + , Just do + release + restoreStack stack ) case term of Syntax.Var index -> @@ -591,10 +596,10 @@ generateTypedTerm env term type_ representation = do typeValue <- Builder $ lift $ Evaluation.evaluate (Context.toEnvironment env.context) termType typeRepresentation <- Builder $ lift $ ClosureConverted.Representation.typeRepresentation (Context.toEnvironment env.context) typeValue termType' <- generateType env termType - (term'', deallocateTerm) <- generateTypedTerm env term' termType' typeRepresentation + (term'', releaseTerm) <- generateTypedTerm env term' termType' typeRepresentation env' <- extend env termType term'' - (result, deallocateBody) <- generateTypedTerm env' body type_ representation - pure (result, (>>) <$> deallocateBody <*> deallocateTerm) + (result, releaseBody) <- generateTypedTerm env' body type_ representation + pure (result, (>>) <$> releaseBody <*> releaseTerm) Syntax.Function _ -> pure (Direct pointerBytesOperand, Nothing) Syntax.Apply global arguments -> do @@ -640,10 +645,12 @@ storeTerm env term returnLocation returnType = indexOperand index env returnTypeSize <- sizeOfType returnType copy returnLocation varOperand returnTypeSize + retains returnLocation returnTypeSize Syntax.Global global -> do operand <- globalConstantOperand global returnTypeSize <- sizeOfType returnType copy returnLocation operand returnTypeSize + retains returnLocation returnTypeSize Syntax.Con con params args -> do (boxity, maybeTag) <- fetch $ Query.ConstructorRepresentation con let tagArgs = @@ -700,10 +707,10 @@ storeTerm env term returnLocation returnType = typeValue <- Builder $ lift $ Evaluation.evaluate (Context.toEnvironment env.context) type_ typeRepresentation <- Builder $ lift $ ClosureConverted.Representation.typeRepresentation (Context.toEnvironment env.context) typeValue type' <- generateType env type_ - (term'', deallocateTerm) <- generateTypedTerm env term' type' typeRepresentation + (term'', releaseTerm) <- generateTypedTerm env term' type' typeRepresentation env' <- extend env type_ term'' storeTerm env' body returnLocation returnType - sequence_ deallocateTerm + sequence_ releaseTerm Syntax.Function _ -> store returnLocation pointerBytesOperand Syntax.Apply global arguments -> do @@ -721,7 +728,7 @@ storeTerm env term returnLocation returnType = Representation.Direct -> do result <- callDirect "call_result" global arguments' store returnLocation result - Representation.Indirect -> do + Representation.Indirect -> callIndirect global arguments' returnLocation deallocateArguments Syntax.Pi {} -> @@ -736,7 +743,7 @@ storeTerm env term returnLocation returnType = (Syntax.Apply (Name.Lifted Builtin.UnknownName 0) [Syntax.Global $ Name.Lifted Builtin.UnitName 0]) maybeDefaultBranch (scrutineeType, scrutineeRepresentation) <- typeOf env scrutinee - (scrutinee', deallocateScrutinee) <- generateTypedTerm env scrutinee scrutineeType scrutineeRepresentation + (scrutinee', releaseScrutinee) <- generateTypedTerm env scrutinee scrutineeType scrutineeRepresentation branches' <- ClosureConverted.Representation.compileBranches branches case branches' of ClosureConverted.Representation.TaggedConstructorBranches Unboxed constructorBranches -> do @@ -750,24 +757,22 @@ storeTerm env term returnLocation returnType = constructorTag [ ( fromIntegral $ shiftL branchTag 1 , do - storeUnboxedBranch env firstConstructorFieldBuilder branch returnLocation returnType + storeBranch env firstConstructorFieldBuilder branch returnLocation returnType deallocateScrutinee' - sequence_ deallocateScrutinee + sequence_ releaseScrutinee pure Assembly.Void ) | (branchTag, branch) <- constructorBranches ] ( do deallocateScrutinee' - sequence_ deallocateScrutinee + sequence_ releaseScrutinee storeTerm env defaultBranch returnLocation returnType pure Assembly.Void ) ClosureConverted.Representation.TaggedConstructorBranches Boxed constructorBranches -> do scrutinee'' <- forceDirect scrutinee' - sequence_ deallocateScrutinee - let constructorBasePointerBuilder = extractHeapPointer "boxed_constructor_pointer" scrutinee'' - firstConstructorFieldOffsetBuilder _ = pure $ Assembly.Lit $ Literal.Integer 0 + let constructorBasePointerBuilder suggestion = extractHeapPointer suggestion scrutinee'' constructorTag <- extractHeapPointerConstructorTag "heap_scrutinee_tag" scrutinee'' void $ switch @@ -775,29 +780,27 @@ storeTerm env term returnLocation returnType = constructorTag [ ( fromIntegral branchTag , do - storeBoxedBranch env constructorBasePointerBuilder firstConstructorFieldOffsetBuilder branch returnLocation returnType + storeBranch env constructorBasePointerBuilder branch returnLocation returnType pure Assembly.Void ) | (branchTag, branch) <- constructorBranches ] ( do storeTerm env defaultBranch returnLocation returnType + sequence_ releaseScrutinee pure Assembly.Void ) ClosureConverted.Representation.UntaggedConstructorBranch Unboxed branch -> do - (scrutinee'', deallocateScrutinee') <- forceIndirect scrutinee' - storeUnboxedBranch env (const $ pure scrutinee'') branch returnLocation returnType - deallocateScrutinee' - sequence_ deallocateScrutinee + (scrutinee'', releaseScrutinee') <- forceIndirect scrutinee' + storeBranch env (const $ pure scrutinee'') branch returnLocation returnType + releaseScrutinee' + sequence_ releaseScrutinee ClosureConverted.Representation.UntaggedConstructorBranch Boxed branch -> do scrutinee'' <- forceDirect scrutinee' - sequence_ deallocateScrutinee - let constructorBasePointerBuilder = extractHeapPointer "boxed_constructor_pointer" scrutinee'' - firstConstructorFieldOffsetBuilder _ = pure $ Assembly.Lit $ Literal.Integer 0 - storeBoxedBranch env constructorBasePointerBuilder firstConstructorFieldOffsetBuilder branch returnLocation returnType + let constructorBasePointerBuilder suggestion = extractHeapPointer suggestion scrutinee'' + storeBranch env constructorBasePointerBuilder branch returnLocation returnType ClosureConverted.Representation.LiteralBranches literalBranches -> do directScrutinee <- forceDirect scrutinee' - sequence_ deallocateScrutinee void $ switch Assembly.Void @@ -814,14 +817,14 @@ storeTerm env term returnLocation returnType = pure Assembly.Void ) -storeUnboxedBranch +storeBranch :: Environment v -> (Assembly.NameSuggestion -> Builder Assembly.Operand) -> Telescope Name Syntax.Type Syntax.Term v -> Assembly.Operand -> Operand -> Builder () -storeUnboxedBranch env constructorFieldBuilder tele returnLocation returnType = +storeBranch env constructorFieldBuilder tele returnLocation returnType = case tele of Telescope.Extend (Name name) type_ _plicity tele' -> do constructorField <- constructorFieldBuilder $ Assembly.NameSuggestion name @@ -830,6 +833,7 @@ storeUnboxedBranch env constructorFieldBuilder tele returnLocation returnType = typeSize <- sizeOfType type' addPointer nameSuggestion constructorField typeSize env' <- extend env type_ $ Indirect constructorField +<<<<<<< HEAD storeUnboxedBranch env' nextConstructorFieldBuilder tele' returnLocation returnType Telescope.Empty branch -> storeTerm env branch returnLocation returnType @@ -858,45 +862,46 @@ storeBoxedBranch env constructorBasePointerBuilder constructorFieldOffsetBuilder env' <- extend env type_ $ Indirect stackConstructorField storeBoxedBranch env' constructorBasePointerBuilder nextConstructorFieldOffsetBuilder tele' returnLocation returnType restoreStack stack + storeBranch env' nextConstructorFieldBuilder tele' returnLocation returnType Telescope.Empty branch -> storeTerm env branch returnLocation returnType generateArguments :: Environment v -> [(Syntax.Term v, Representation)] -> Builder ([(Assembly.Type, Assembly.Operand)], Builder ()) generateArguments env arguments = do - (argumentGenerators, outerDeallocators) <- mapAndUnzipM (uncurry $ generateArgument env) arguments - (arguments', innerDeallocators) <- unzip <$> sequence argumentGenerators + (argumentGenerators, outerReleases) <- mapAndUnzipM (uncurry $ generateArgument env) arguments + (arguments', innerReleases) <- unzip <$> sequence argumentGenerators pure ( concat arguments' , do - sequence_ $ reverse innerDeallocators - sequence_ $ reverse outerDeallocators + sequence_ $ reverse innerReleases + sequence_ $ reverse outerReleases ) generateArgument :: Environment v -> Syntax.Term v -> Representation -> Builder (Builder ([(Assembly.Type, Assembly.Operand)], Builder ()), Builder ()) generateArgument env term representation = case representation of Representation.Empty -> do - (_, deallocateTerm) <- generateTypedTerm env term (Direct emptyTypeOperand) representation + (_, releaseTerm) <- generateTypedTerm env term (Direct emptyTypeOperand) representation pure ( pure ([], pure ()) - , sequence_ deallocateTerm + , sequence_ releaseTerm ) Representation.Direct -> do - (term', deallocateTerm) <- generateTypedTerm env term (Direct directTypeOperand) representation + (term', releaseTerm) <- generateTypedTerm env term (Direct directTypeOperand) representation pure ( do directTerm <- forceDirect term' pure ([(Assembly.Word, directTerm)], pure ()) - , sequence_ deallocateTerm + , sequence_ releaseTerm ) Representation.Indirect -> do (type_, representation_) <- typeOf env term - (termOperand, deallocateTermOperand) <- generateTypedTerm env term type_ representation_ + (termOperand, releaseTermOperand) <- generateTypedTerm env term type_ representation_ pure ( do - (termLocation, deallocateTerm) <- forceIndirect termOperand - pure ([(Assembly.WordPointer, termLocation)], deallocateTerm) - , sequence_ deallocateTermOperand + (termLocation, releaseTerm) <- forceIndirect termOperand + pure ([(Assembly.WordPointer, termLocation)], releaseTerm) + , sequence_ releaseTermOperand ) ------------------------------------------------------------------------------- diff --git a/src/Query.hs b/src/Query.hs index 1708ac0e..cb7f65fe 100644 --- a/src/Query.hs +++ b/src/Query.hs @@ -83,7 +83,6 @@ data Query a where ConstructorRepresentations :: Name.Qualified -> Query (Boxity, Maybe (HashMap Name.Constructor Int)) ConstructorRepresentation :: Name.QualifiedConstructor -> Query (Boxity, Maybe Int) Assembly :: Name.Lifted -> Query (Maybe Assembly.Definition) - HeapAllocates :: Name.Lifted -> Query Bool AssemblyModule :: Name.Module -> Query [(Name.Lifted, Assembly.Definition)] LLVMModule :: Name.Module -> Query Lazy.ByteString LLVMModuleInitModule :: Query Lazy.ByteString @@ -144,10 +143,9 @@ instance Hashable (Query a) where ConstructorRepresentations a -> h 30 a ConstructorRepresentation a -> h 31 a Assembly a -> h 32 a - HeapAllocates a -> h 33 a - AssemblyModule a -> h 34 a - LLVMModule a -> h 35 a - LLVMModuleInitModule -> h 36 () + AssemblyModule a -> h 33 a + LLVMModule a -> h 34 a + LLVMModuleInitModule -> h 35 () where {-# INLINE h #-} h :: (Hashable b) => Int -> b -> Int diff --git a/src/Representation.hs b/src/Representation.hs index 3b20b9e8..c16b3381 100644 --- a/src/Representation.hs +++ b/src/Representation.hs @@ -1,6 +1,7 @@ {-# LANGUAGE BlockArguments #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Representation where @@ -25,20 +26,15 @@ instance Semigroup Representation where _ <> _ = Indirect instance Monoid Representation where - mempty = - Empty + mempty = Empty instance Pretty Representation where - pretty representation = - case representation of - Empty -> - "empty" - Direct -> - "direct" - Indirect -> - "indirect" - -maxM :: (Monad m) => [m Representation] -> m Representation + pretty = \case + Empty -> "empty" + Direct -> "direct" + Indirect -> "indirect" + +maxM :: Monad m => [m Representation] -> m Representation maxM [] = pure mempty maxM (m : ms) = do representation <- m diff --git a/src/Rules.hs b/src/Rules.hs index 2ff6454e..a329cf79 100644 --- a/src/Rules.hs +++ b/src/Rules.hs @@ -11,8 +11,6 @@ module Rules where -import qualified Assembly.HeapAllocates -import qualified Assembly.HeapAllocates as Assembly import qualified AssemblyToLLVM import qualified Builtin import qualified ClosureConversion @@ -458,13 +456,6 @@ rules sourceDirectories files readFile_ (Writer (Writer query)) = noError do definition <- fetch $ ClosureConverted name runM $ ClosureConvertedToAssembly.generateDefinition name definition - HeapAllocates name -> - noError do - maybeAssembly <- fetch $ Assembly name - case maybeAssembly of - Nothing -> pure False - Just assembly -> - runM $ Assembly.HeapAllocates.run $ Assembly.definitionHeapAllocates assembly AssemblyModule module_ -> noError do names <- fetch $ LambdaLiftedModuleDefinitions module_