unsafe fn llvm_type(&mut self, ty: &Type) -> WeldResult<LLVMTypeRef> {
        use crate::ast::ScalarKind::*;
        use crate::ast::Type::*;
        let result = match *ty {
            Builder(_, _) => {
                use self::builder::BuilderExpressionGen;
                self.builder_type(ty)?
            }
            Dict(ref key, ref value) => {
                use self::eq::GenEq;
                if !self.dictionaries.contains_key(ty) {
                    let key_ty = self.llvm_type(key)?;
                    let value_ty = self.llvm_type(value)?;
                    let key_comparator = self.gen_eq_fn(key)?;
                    let dict = dict::Dict::define(
                        "dict",
                        key_ty,
                        key_comparator,
                        value_ty,
                        self.context,
                        self.module,
                    );
                    self.dictionaries.insert(ty.clone(), dict);
                }
                self.dictionaries[ty].dict_ty
            }
            Scalar(kind) => match kind {
                Bool => self.bool_type(),
                I8 | U8 => self.i8_type(),
                I16 | U16 => self.i16_type(),
                I32 | U32 => self.i32_type(),
                I64 | U64 => self.i64_type(),
                F32 => self.f32_type(),
                F64 => self.f64_type(),
            },
            Simd(kind) => {
                let base = self.llvm_type(&Scalar(kind))?;
                LLVMVectorType(base, LLVM_VECTOR_WIDTH)
            }
            Struct(ref elems) => {
                if !self.struct_names.contains_key(ty) {
                    let name = CString::new(format!("s{}", self.struct_index)).unwrap();
                    self.struct_index += 1;
                    let mut llvm_types: Vec<_> = elems
                        .iter()
                        .map(&mut |t| self.llvm_type(t))
                        .collect::<WeldResult<_>>()?;
                    let struct_ty = LLVMStructCreateNamed(self.context, name.as_ptr());
                    LLVMStructSetBody(
                        struct_ty,
                        llvm_types.as_mut_ptr(),
                        llvm_types.len() as u32,
                        0,
                    );
                    self.struct_names.insert(ty.clone(), name);
                }
                LLVMGetTypeByName(
                    self.module,
                    self.struct_names.get(ty).cloned().unwrap().as_ptr(),
                )
            }
            Vector(ref elem_type) => {
                // Vectors are a named type, so only generate the name once.
                if !self.vectors.contains_key(elem_type) {
                    let llvm_elem_type = self.llvm_type(elem_type)?;
                    let vector =
                        vector::Vector::define("vec", llvm_elem_type, self.context, self.module);
                    self.vectors.insert(elem_type.as_ref().clone(), vector);
                }
                self.vectors[elem_type].vector_ty
            }
            Function(_, _) | Unknown | Alias(_, _) => unreachable!(),
        };
        Ok(result)
    }
Returns the LLVM type for a Weld Type.

This method may generate auxillary code before returning the type. For example, for complex
data structures, this function may generate a definition for the data structure first.
weld/src/codegen/llvm2/mod.rs