func (v *Codegen) enumTypeToLLVMType(typ ast.EnumType, gcon *ast.GenericContext) llvm.Type { if typ.Simple { // TODO: Handle other integer size, maybe dynamic depending on max value? (1 / 2) return llvm.IntType(32) } return llvm.StructType(v.enumTypeToLLVMTypeFields(typ, gcon), true) }
func (v *Codegen) enumTypeToLLVMTypeFields(typ ast.EnumType, gcon *ast.GenericContext) []llvm.Type { longestLength := uint64(0) for _, member := range typ.Members { memLength := v.targetData.TypeAllocSize(v.typeToLLVMType(member.Type, gcon)) if memLength > longestLength { longestLength = memLength } } // TODO: verify no overflow return []llvm.Type{enumTagType, llvm.ArrayType(llvm.IntType(8), int(longestLength))} }
func (v *Codegen) primitiveTypeToLLVMType(typ ast.PrimitiveType) llvm.Type { switch typ { case ast.PRIMITIVE_int, ast.PRIMITIVE_uint, ast.PRIMITIVE_uintptr: return v.targetData.IntPtrType() case ast.PRIMITIVE_s8, ast.PRIMITIVE_u8: return llvm.IntType(8) case ast.PRIMITIVE_s16, ast.PRIMITIVE_u16: return llvm.IntType(16) case ast.PRIMITIVE_s32, ast.PRIMITIVE_u32: return llvm.IntType(32) case ast.PRIMITIVE_s64, ast.PRIMITIVE_u64: return llvm.IntType(64) case ast.PRIMITIVE_s128, ast.PRIMITIVE_u128: return llvm.IntType(128) case ast.PRIMITIVE_f32: return llvm.FloatType() case ast.PRIMITIVE_f64: return llvm.DoubleType() case ast.PRIMITIVE_f128: return llvm.FP128Type() case ast.PRIMITIVE_bool: return llvm.IntType(1) case ast.PRIMITIVE_void: return llvm.VoidType() default: panic("Unimplemented primitive type in LLVM codegen") } }
func (v *Codegen) addEnumType(typ ast.EnumType, name string, gcon *ast.GenericContext) { if _, ok := v.namedTypeLookup[name]; ok { return } if typ.Simple { // TODO: Handle other integer size, maybe dynamic depending on max value? v.namedTypeLookup[name] = llvm.IntType(32) } else { enum := v.curFile.LlvmModule.Context().StructCreateNamed(name) v.namedTypeLookup[name] = enum for _, member := range typ.Members { if named, ok := member.Type.(*ast.NamedType); ok { v.addNamedType(named, ast.TypeReferenceMangledName(ast.MANGLE_ARK_UNSTABLE, &ast.TypeReference{BaseType: member.Type}, gcon), gcon) } } enum.StructSetBody(v.enumTypeToLLVMTypeFields(typ, gcon), false) } }
func (v *Codegen) enumMemberTypeToPaddedLLVMType(enumType ast.EnumType, memberIdx int, gcon *ast.GenericContext) llvm.Type { longestLength := uint64(0) for _, member := range enumType.Members { memLength := v.targetData.TypeAllocSize(v.typeToLLVMType(member.Type, gcon)) if memLength > longestLength { longestLength = memLength } } member := enumType.Members[memberIdx] actualType := v.typeToLLVMType(member.Type, gcon) amountPad := longestLength - v.targetData.TypeAllocSize(actualType) if amountPad > 0 { types := make([]llvm.Type, actualType.StructElementTypesCount()+1) copy(types, actualType.StructElementTypes()) types[len(types)-1] = llvm.ArrayType(llvm.IntType(8), int(amountPad)) return llvm.StructType(types, false) } else { return actualType } }