Beispiel #1
0
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)
}
Beispiel #2
0
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))}
}
Beispiel #3
0
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")
	}
}
Beispiel #4
0
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)
	}
}
Beispiel #5
0
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
	}
}