]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/mir/constant.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_trans / mir / constant.rs
CommitLineData
54a0048b
SL
1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
a7813a04 11use llvm::{self, ValueRef};
54a0048b 12use rustc::middle::const_val::ConstVal;
9e0c209e 13use rustc_const_eval::{ErrKind, ConstEvalErr, report_const_eval_err};
54a0048b 14use rustc_const_math::ConstInt::*;
3157f602 15use rustc_const_math::ConstFloat::*;
32a655c1 16use rustc_const_math::{ConstInt, ConstMathErr};
a7813a04
XL
17use rustc::hir::def_id::DefId;
18use rustc::infer::TransNormalize;
c30ab7b3 19use rustc::mir;
a7813a04 20use rustc::mir::tcx::LvalueTy;
32a655c1 21use rustc::ty::{self, layout, Ty, TyCtxt, TypeFoldable};
a7813a04 22use rustc::ty::cast::{CastTy, IntTy};
8bb4bdeb 23use rustc::ty::subst::{Kind, Substs, Subst};
3157f602 24use rustc_data_structures::indexed_vec::{Idx, IndexVec};
9e0c209e 25use {abi, adt, base, Disr, machine};
a7813a04 26use callee::Callee;
32a655c1
SL
27use builder::Builder;
28use common::{self, CrateContext, const_get_elt, val_ty};
29use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral, C_big_integral};
30use common::{C_null, C_struct, C_str_slice, C_undef, C_uint, C_vector, is_undef};
31use common::const_to_opt_u128;
9e0c209e 32use consts;
a7813a04 33use monomorphize::{self, Instance};
54a0048b
SL
34use type_of;
35use type_::Type;
a7813a04 36use value::Value;
54a0048b 37
32a655c1 38use syntax_pos::Span;
54a0048b 39
5bcae85e 40use std::fmt;
a7813a04 41use std::ptr;
54a0048b 42
32a655c1 43use super::lvalue::Alignment;
a7813a04
XL
44use super::operand::{OperandRef, OperandValue};
45use super::MirContext;
54a0048b 46
a7813a04
XL
47/// A sized constant rvalue.
48/// The LLVM type might not be the same for a single Rust type,
49/// e.g. each enum variant would have its own LLVM struct type.
50#[derive(Copy, Clone)]
51pub struct Const<'tcx> {
52 pub llval: ValueRef,
53 pub ty: Ty<'tcx>
54}
54a0048b 55
a7813a04
XL
56impl<'tcx> Const<'tcx> {
57 pub fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
58 Const {
59 llval: llval,
60 ty: ty
54a0048b
SL
61 }
62 }
63
8bb4bdeb
XL
64 pub fn from_constint<'a>(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt)
65 -> Const<'tcx> {
66 let tcx = ccx.tcx();
67 let (llval, ty) = match *ci {
68 I8(v) => (C_integral(Type::i8(ccx), v as u64, true), tcx.types.i8),
69 I16(v) => (C_integral(Type::i16(ccx), v as u64, true), tcx.types.i16),
70 I32(v) => (C_integral(Type::i32(ccx), v as u64, true), tcx.types.i32),
71 I64(v) => (C_integral(Type::i64(ccx), v as u64, true), tcx.types.i64),
72 I128(v) => (C_big_integral(Type::i128(ccx), v as u128), tcx.types.i128),
73 Isize(v) => {
74 let i = v.as_i64(ccx.tcx().sess.target.int_type);
75 (C_integral(Type::int(ccx), i as u64, true), tcx.types.isize)
76 },
77 U8(v) => (C_integral(Type::i8(ccx), v as u64, false), tcx.types.u8),
78 U16(v) => (C_integral(Type::i16(ccx), v as u64, false), tcx.types.u16),
79 U32(v) => (C_integral(Type::i32(ccx), v as u64, false), tcx.types.u32),
80 U64(v) => (C_integral(Type::i64(ccx), v, false), tcx.types.u64),
81 U128(v) => (C_big_integral(Type::i128(ccx), v), tcx.types.u128),
82 Usize(v) => {
83 let u = v.as_u64(ccx.tcx().sess.target.uint_type);
84 (C_integral(Type::int(ccx), u, false), tcx.types.usize)
85 },
86 };
87 Const { llval: llval, ty: ty }
88 }
89
a7813a04
XL
90 /// Translate ConstVal into a LLVM constant value.
91 pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
92 cv: ConstVal,
93 ty: Ty<'tcx>)
94 -> Const<'tcx> {
54a0048b 95 let llty = type_of::type_of(ccx, ty);
a7813a04 96 let val = match cv {
3157f602
XL
97 ConstVal::Float(F32(v)) => C_floating_f64(v as f64, llty),
98 ConstVal::Float(F64(v)) => C_floating_f64(v, llty),
54a0048b 99 ConstVal::Bool(v) => C_bool(ccx, v),
8bb4bdeb 100 ConstVal::Integral(ref i) => return Const::from_constint(ccx, i),
54a0048b
SL
101 ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
102 ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
103 ConstVal::Struct(_) | ConstVal::Tuple(_) |
104 ConstVal::Array(..) | ConstVal::Repeat(..) |
8bb4bdeb 105 ConstVal::Function(..) => {
3157f602 106 bug!("MIR must not use `{:?}` (which refers to a local ID)", cv)
54a0048b
SL
107 }
108 ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
a7813a04
XL
109 };
110
111 assert!(!ty.has_erasable_regions());
112
113 Const::new(val, ty)
114 }
115
3157f602
XL
116 fn get_pair(&self) -> (ValueRef, ValueRef) {
117 (const_get_elt(self.llval, &[0]),
118 const_get_elt(self.llval, &[1]))
119 }
120
a7813a04 121 fn get_fat_ptr(&self) -> (ValueRef, ValueRef) {
3157f602
XL
122 assert_eq!(abi::FAT_PTR_ADDR, 0);
123 assert_eq!(abi::FAT_PTR_EXTRA, 1);
124 self.get_pair()
a7813a04
XL
125 }
126
127 fn as_lvalue(&self) -> ConstLvalue<'tcx> {
128 ConstLvalue {
129 base: Base::Value(self.llval),
130 llextra: ptr::null_mut(),
131 ty: self.ty
132 }
133 }
134
135 pub fn to_operand<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
136 let llty = type_of::immediate_type_of(ccx, self.ty);
137 let llvalty = val_ty(self.llval);
138
3157f602
XL
139 let val = if llty == llvalty && common::type_is_imm_pair(ccx, self.ty) {
140 let (a, b) = self.get_pair();
141 OperandValue::Pair(a, b)
142 } else if llty == llvalty && common::type_is_immediate(ccx, self.ty) {
a7813a04
XL
143 // If the types match, we can use the value directly.
144 OperandValue::Immediate(self.llval)
145 } else {
146 // Otherwise, or if the value is not immediate, we create
147 // a constant LLVM global and cast its address if necessary.
148 let align = type_of::align_of(ccx, self.ty);
149 let ptr = consts::addr_of(ccx, self.llval, align, "const");
32a655c1 150 OperandValue::Ref(consts::ptrcast(ptr, llty.ptr_to()), Alignment::AbiAligned)
a7813a04
XL
151 };
152
153 OperandRef {
154 val: val,
155 ty: self.ty
156 }
157 }
158}
159
5bcae85e
SL
160impl<'tcx> fmt::Debug for Const<'tcx> {
161 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162 write!(f, "Const({:?}: {:?})", Value(self.llval), self.ty)
163 }
164}
165
a7813a04
XL
166#[derive(Copy, Clone)]
167enum Base {
168 /// A constant value without an unique address.
169 Value(ValueRef),
170
171 /// String literal base pointer (cast from array).
172 Str(ValueRef),
173
174 /// The address of a static.
175 Static(ValueRef)
176}
177
178/// An lvalue as seen from a constant.
179#[derive(Copy, Clone)]
180struct ConstLvalue<'tcx> {
181 base: Base,
182 llextra: ValueRef,
183 ty: Ty<'tcx>
184}
185
186impl<'tcx> ConstLvalue<'tcx> {
187 fn to_const(&self, span: Span) -> Const<'tcx> {
188 match self.base {
189 Base::Value(val) => Const::new(val, self.ty),
190 Base::Str(ptr) => {
191 span_bug!(span, "loading from `str` ({:?}) in constant",
192 Value(ptr))
193 }
194 Base::Static(val) => {
195 span_bug!(span, "loading from `static` ({:?}) in constant",
196 Value(val))
197 }
198 }
199 }
200
201 pub fn len<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
202 match self.ty.sty {
203 ty::TyArray(_, n) => C_uint(ccx, n),
204 ty::TySlice(_) | ty::TyStr => {
205 assert!(self.llextra != ptr::null_mut());
206 self.llextra
207 }
208 _ => bug!("unexpected type `{}` in ConstLvalue::len", self.ty)
209 }
210 }
211}
212
213/// Machinery for translating a constant's MIR to LLVM values.
214/// FIXME(eddyb) use miri and lower its allocations to LLVM.
215struct MirConstContext<'a, 'tcx: 'a> {
216 ccx: &'a CrateContext<'a, 'tcx>,
217 mir: &'a mir::Mir<'tcx>,
218
219 /// Type parameters for const fn and associated constants.
220 substs: &'tcx Substs<'tcx>,
221
3157f602
XL
222 /// Values of locals in a constant or const fn.
223 locals: IndexVec<mir::Local, Option<Const<'tcx>>>
a7813a04
XL
224}
225
226
227impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
228 fn new(ccx: &'a CrateContext<'a, 'tcx>,
229 mir: &'a mir::Mir<'tcx>,
230 substs: &'tcx Substs<'tcx>,
c30ab7b3 231 args: IndexVec<mir::Local, Const<'tcx>>)
a7813a04 232 -> MirConstContext<'a, 'tcx> {
3157f602 233 let mut context = MirConstContext {
a7813a04
XL
234 ccx: ccx,
235 mir: mir,
236 substs: substs,
c30ab7b3 237 locals: (0..mir.local_decls.len()).map(|_| None).collect(),
3157f602
XL
238 };
239 for (i, arg) in args.into_iter().enumerate() {
c30ab7b3
SL
240 // Locals after local 0 are the function arguments
241 let index = mir::Local::new(i + 1);
3157f602 242 context.locals[index] = Some(arg);
54a0048b 243 }
3157f602 244 context
54a0048b
SL
245 }
246
a7813a04 247 fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
32a655c1 248 instance: Instance<'tcx>,
c30ab7b3 249 args: IndexVec<mir::Local, Const<'tcx>>)
8bb4bdeb 250 -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
32a655c1 251 let instance = instance.resolve_const(ccx.shared());
c30ab7b3 252 let mir = ccx.tcx().item_mir(instance.def);
a7813a04
XL
253 MirConstContext::new(ccx, &mir, instance.substs, args).trans()
254 }
255
256 fn monomorphize<T>(&self, value: &T) -> T
257 where T: TransNormalize<'tcx>
258 {
9e0c209e 259 monomorphize::apply_param_substs(self.ccx.shared(),
a7813a04
XL
260 self.substs,
261 value)
262 }
263
8bb4bdeb 264 fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
a7813a04
XL
265 let tcx = self.ccx.tcx();
266 let mut bb = mir::START_BLOCK;
3157f602
XL
267
268 // Make sure to evaluate all statemenets to
269 // report as many errors as we possibly can.
270 let mut failure = Ok(());
271
a7813a04 272 loop {
3157f602 273 let data = &self.mir[bb];
a7813a04 274 for statement in &data.statements {
3157f602 275 let span = statement.source_info.span;
a7813a04
XL
276 match statement.kind {
277 mir::StatementKind::Assign(ref dest, ref rvalue) => {
5bcae85e 278 let ty = dest.ty(self.mir, tcx);
a7813a04 279 let ty = self.monomorphize(&ty).to_ty(tcx);
3157f602
XL
280 match self.const_rvalue(rvalue, ty, span) {
281 Ok(value) => self.store(dest, value, span),
282 Err(err) => if failure.is_ok() { failure = Err(err); }
283 }
a7813a04 284 }
5bcae85e 285 mir::StatementKind::StorageLive(_) |
9e0c209e
SL
286 mir::StatementKind::StorageDead(_) |
287 mir::StatementKind::Nop => {}
8bb4bdeb 288 mir::StatementKind::InlineAsm { .. } |
5bcae85e 289 mir::StatementKind::SetDiscriminant{ .. } => {
8bb4bdeb 290 span_bug!(span, "{:?} should not appear in constants?", statement.kind);
5bcae85e 291 }
a7813a04
XL
292 }
293 }
294
295 let terminator = data.terminator();
3157f602 296 let span = terminator.source_info.span;
a7813a04
XL
297 bb = match terminator.kind {
298 mir::TerminatorKind::Drop { target, .. } | // No dropping.
299 mir::TerminatorKind::Goto { target } => target,
300 mir::TerminatorKind::Return => {
3157f602 301 failure?;
c30ab7b3 302 return Ok(self.locals[mir::RETURN_POINTER].unwrap_or_else(|| {
a7813a04 303 span_bug!(span, "no returned value in constant");
3157f602 304 }));
a7813a04
XL
305 }
306
3157f602 307 mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, .. } => {
a7813a04 308 let cond = self.const_operand(cond, span)?;
3157f602
XL
309 let cond_bool = common::const_to_uint(cond.llval) != 0;
310 if cond_bool != expected {
311 let err = match *msg {
312 mir::AssertMessage::BoundsCheck { ref len, ref index } => {
313 let len = self.const_operand(len, span)?;
314 let index = self.const_operand(index, span)?;
315 ErrKind::IndexOutOfBounds {
316 len: common::const_to_uint(len.llval),
317 index: common::const_to_uint(index.llval)
318 }
319 }
320 mir::AssertMessage::Math(ref err) => {
321 ErrKind::Math(err.clone())
322 }
323 };
9e0c209e
SL
324
325 let err = ConstEvalErr{ span: span, kind: err };
8bb4bdeb 326 report_const_eval_err(tcx, &err, span, "expression");
9e0c209e 327 failure = Err(err);
a7813a04 328 }
3157f602 329 target
a7813a04
XL
330 }
331
332 mir::TerminatorKind::Call { ref func, ref args, ref destination, .. } => {
5bcae85e 333 let fn_ty = func.ty(self.mir, tcx);
a7813a04
XL
334 let fn_ty = self.monomorphize(&fn_ty);
335 let instance = match fn_ty.sty {
336 ty::TyFnDef(def_id, substs, _) => {
337 Instance::new(def_id, substs)
338 }
339 _ => span_bug!(span, "calling {:?} (of type {}) in constant",
340 func, fn_ty)
341 };
342
3157f602
XL
343 let mut const_args = IndexVec::with_capacity(args.len());
344 for arg in args {
345 match self.const_operand(arg, span) {
346 Ok(arg) => { const_args.push(arg); },
347 Err(err) => if failure.is_ok() { failure = Err(err); }
348 }
a7813a04 349 }
a7813a04 350 if let Some((ref dest, target)) = *destination {
3157f602
XL
351 match MirConstContext::trans_def(self.ccx, instance, const_args) {
352 Ok(value) => self.store(dest, value, span),
353 Err(err) => if failure.is_ok() { failure = Err(err); }
354 }
a7813a04
XL
355 target
356 } else {
3157f602 357 span_bug!(span, "diverging {:?} in constant", terminator.kind);
a7813a04
XL
358 }
359 }
360 _ => span_bug!(span, "{:?} in constant", terminator.kind)
361 };
362 }
363 }
364
365 fn store(&mut self, dest: &mir::Lvalue<'tcx>, value: Const<'tcx>, span: Span) {
c30ab7b3 366 if let mir::Lvalue::Local(index) = *dest {
3157f602
XL
367 self.locals[index] = Some(value);
368 } else {
369 span_bug!(span, "assignment to {:?} in constant", dest);
370 }
a7813a04
XL
371 }
372
373 fn const_lvalue(&self, lvalue: &mir::Lvalue<'tcx>, span: Span)
8bb4bdeb 374 -> Result<ConstLvalue<'tcx>, ConstEvalErr<'tcx>> {
a7813a04 375 let tcx = self.ccx.tcx();
3157f602 376
c30ab7b3 377 if let mir::Lvalue::Local(index) = *lvalue {
3157f602
XL
378 return Ok(self.locals[index].unwrap_or_else(|| {
379 span_bug!(span, "{:?} not initialized", lvalue)
380 }).as_lvalue());
381 }
382
a7813a04 383 let lvalue = match *lvalue {
c30ab7b3 384 mir::Lvalue::Local(_) => bug!(), // handled above
8bb4bdeb 385 mir::Lvalue::Static(box mir::Static { def_id, ty }) => {
a7813a04 386 ConstLvalue {
9e0c209e 387 base: Base::Static(consts::get_static(self.ccx, def_id)),
a7813a04 388 llextra: ptr::null_mut(),
8bb4bdeb 389 ty: self.monomorphize(&ty),
a7813a04
XL
390 }
391 }
a7813a04
XL
392 mir::Lvalue::Projection(ref projection) => {
393 let tr_base = self.const_lvalue(&projection.base, span)?;
394 let projected_ty = LvalueTy::Ty { ty: tr_base.ty }
395 .projection_ty(tcx, &projection.elem);
396 let base = tr_base.to_const(span);
397 let projected_ty = self.monomorphize(&projected_ty).to_ty(tcx);
32a655c1 398 let is_sized = self.ccx.shared().type_is_sized(projected_ty);
a7813a04
XL
399
400 let (projected, llextra) = match projection.elem {
401 mir::ProjectionElem::Deref => {
402 let (base, extra) = if is_sized {
403 (base.llval, ptr::null_mut())
404 } else {
405 base.get_fat_ptr()
406 };
407 if self.ccx.statics().borrow().contains_key(&base) {
408 (Base::Static(base), extra)
409 } else if let ty::TyStr = projected_ty.sty {
410 (Base::Str(base), extra)
411 } else {
9e0c209e
SL
412 let v = base;
413 let v = self.ccx.const_unsized().borrow().get(&v).map_or(v, |&v| v);
414 let mut val = unsafe { llvm::LLVMGetInitializer(v) };
a7813a04
XL
415 if val.is_null() {
416 span_bug!(span, "dereference of non-constant pointer `{:?}`",
417 Value(base));
418 }
9e0c209e
SL
419 if projected_ty.is_bool() {
420 unsafe {
421 val = llvm::LLVMConstTrunc(val, Type::i1(self.ccx).to_ref());
422 }
423 }
a7813a04
XL
424 (Base::Value(val), extra)
425 }
426 }
427 mir::ProjectionElem::Field(ref field, _) => {
9e0c209e 428 let llprojected = adt::const_get_field(self.ccx, tr_base.ty, base.llval,
a7813a04
XL
429 Disr(0), field.index());
430 let llextra = if is_sized {
431 ptr::null_mut()
432 } else {
433 tr_base.llextra
434 };
435 (Base::Value(llprojected), llextra)
436 }
437 mir::ProjectionElem::Index(ref index) => {
438 let llindex = self.const_operand(index, span)?.llval;
439
32a655c1 440 let iv = if let Some(iv) = common::const_to_opt_u128(llindex, false) {
a7813a04
XL
441 iv
442 } else {
443 span_bug!(span, "index is not an integer-constant expression")
444 };
3157f602
XL
445
446 // Produce an undef instead of a LLVM assertion on OOB.
447 let len = common::const_to_uint(tr_base.len(self.ccx));
32a655c1 448 let llelem = if iv < len as u128 {
3157f602
XL
449 const_get_elt(base.llval, &[iv as u32])
450 } else {
451 C_undef(type_of::type_of(self.ccx, projected_ty))
452 };
453
454 (Base::Value(llelem), ptr::null_mut())
a7813a04
XL
455 }
456 _ => span_bug!(span, "{:?} in constant", projection.elem)
457 };
458 ConstLvalue {
459 base: projected,
460 llextra: llextra,
461 ty: projected_ty
462 }
463 }
464 };
465 Ok(lvalue)
466 }
467
468 fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
8bb4bdeb 469 -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
5bcae85e
SL
470 debug!("const_operand({:?} @ {:?})", operand, span);
471 let result = match *operand {
a7813a04
XL
472 mir::Operand::Consume(ref lvalue) => {
473 Ok(self.const_lvalue(lvalue, span)?.to_const(span))
474 }
475
476 mir::Operand::Constant(ref constant) => {
477 let ty = self.monomorphize(&constant.ty);
478 match constant.literal.clone() {
479 mir::Literal::Item { def_id, substs } => {
480 // Shortcut for zero-sized types, including function item
481 // types, which would not work with MirConstContext.
482 if common::type_is_zero_size(self.ccx, ty) {
483 let llty = type_of::type_of(self.ccx, ty);
484 return Ok(Const::new(C_null(llty), ty));
485 }
486
487 let substs = self.monomorphize(&substs);
488 let instance = Instance::new(def_id, substs);
3157f602 489 MirConstContext::trans_def(self.ccx, instance, IndexVec::new())
a7813a04
XL
490 }
491 mir::Literal::Promoted { index } => {
492 let mir = &self.mir.promoted[index];
3157f602 493 MirConstContext::new(self.ccx, mir, self.substs, IndexVec::new()).trans()
a7813a04
XL
494 }
495 mir::Literal::Value { value } => {
496 Ok(Const::from_constval(self.ccx, value, ty))
497 }
498 }
499 }
5bcae85e
SL
500 };
501 debug!("const_operand({:?} @ {:?}) = {:?}", operand, span,
502 result.as_ref().ok());
503 result
504 }
505
506 fn const_array(&self, array_ty: Ty<'tcx>, fields: &[ValueRef])
507 -> Const<'tcx>
508 {
509 let elem_ty = array_ty.builtin_index().unwrap_or_else(|| {
510 bug!("bad array type {:?}", array_ty)
511 });
512 let llunitty = type_of::type_of(self.ccx, elem_ty);
513 // If the array contains enums, an LLVM array won't work.
514 let val = if fields.iter().all(|&f| val_ty(f) == llunitty) {
515 C_array(llunitty, fields)
516 } else {
517 C_struct(self.ccx, fields, false)
518 };
519 Const::new(val, array_ty)
a7813a04
XL
520 }
521
522 fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
523 dest_ty: Ty<'tcx>, span: Span)
8bb4bdeb 524 -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
a7813a04 525 let tcx = self.ccx.tcx();
5bcae85e 526 debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span);
a7813a04
XL
527 let val = match *rvalue {
528 mir::Rvalue::Use(ref operand) => self.const_operand(operand, span)?,
529
530 mir::Rvalue::Repeat(ref elem, ref count) => {
531 let elem = self.const_operand(elem, span)?;
8bb4bdeb 532 let size = count.as_u64(tcx.sess.target.uint_type);
a7813a04 533 let fields = vec![elem.llval; size as usize];
5bcae85e 534 self.const_array(dest_ty, &fields)
a7813a04
XL
535 }
536
537 mir::Rvalue::Aggregate(ref kind, ref operands) => {
3157f602
XL
538 // Make sure to evaluate all operands to
539 // report as many errors as we possibly can.
540 let mut fields = Vec::with_capacity(operands.len());
541 let mut failure = Ok(());
542 for operand in operands {
543 match self.const_operand(operand, span) {
544 Ok(val) => fields.push(val.llval),
545 Err(err) => if failure.is_ok() { failure = Err(err); }
546 }
547 }
548 failure?;
a7813a04 549
5bcae85e 550 match *kind {
8bb4bdeb 551 mir::AggregateKind::Array(_) => {
5bcae85e 552 self.const_array(dest_ty, &fields)
a7813a04 553 }
5bcae85e
SL
554 mir::AggregateKind::Adt(..) |
555 mir::AggregateKind::Closure(..) |
556 mir::AggregateKind::Tuple => {
32a655c1 557 Const::new(trans_const(self.ccx, dest_ty, kind, &fields), dest_ty)
5bcae85e
SL
558 }
559 }
a7813a04
XL
560 }
561
562 mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
563 let operand = self.const_operand(source, span)?;
564 let cast_ty = self.monomorphize(&cast_ty);
565
566 let val = match *kind {
567 mir::CastKind::ReifyFnPointer => {
568 match operand.ty.sty {
569 ty::TyFnDef(def_id, substs, _) => {
570 Callee::def(self.ccx, def_id, substs)
9e0c209e 571 .reify(self.ccx)
a7813a04
XL
572 }
573 _ => {
574 span_bug!(span, "{} cannot be reified to a fn ptr",
575 operand.ty)
576 }
577 }
578 }
8bb4bdeb
XL
579 mir::CastKind::ClosureFnPointer => {
580 match operand.ty.sty {
581 ty::TyClosure(def_id, substs) => {
582 // Get the def_id for FnOnce::call_once
583 let fn_once = tcx.lang_items.fn_once_trait().unwrap();
584 let call_once = tcx
585 .global_tcx().associated_items(fn_once)
586 .find(|it| it.kind == ty::AssociatedKind::Method)
587 .unwrap().def_id;
588 // Now create its substs [Closure, Tuple]
589 let input = tcx.closure_type(def_id)
590 .subst(tcx, substs.substs).input(0);
591 let substs = tcx.mk_substs([operand.ty, input.skip_binder()]
592 .iter().cloned().map(Kind::from));
593 Callee::def(self.ccx, call_once, substs)
594 .reify(self.ccx)
595 }
596 _ => {
597 bug!("{} cannot be cast to a fn ptr", operand.ty)
598 }
599 }
600 }
a7813a04
XL
601 mir::CastKind::UnsafeFnPointer => {
602 // this is a no-op at the LLVM level
603 operand.llval
604 }
605 mir::CastKind::Unsize => {
606 // unsize targets other than to a fat pointer currently
607 // can't be in constants.
32a655c1 608 assert!(common::type_is_fat_ptr(self.ccx, cast_ty));
a7813a04
XL
609
610 let pointee_ty = operand.ty.builtin_deref(true, ty::NoPreference)
611 .expect("consts: unsizing got non-pointer type").ty;
32a655c1 612 let (base, old_info) = if !self.ccx.shared().type_is_sized(pointee_ty) {
a7813a04
XL
613 // Normally, the source is a thin pointer and we are
614 // adding extra info to make a fat pointer. The exception
615 // is when we are upcasting an existing object fat pointer
616 // to use a different vtable. In that case, we want to
617 // load out the original data pointer so we can repackage
618 // it.
619 let (base, extra) = operand.get_fat_ptr();
620 (base, Some(extra))
621 } else {
622 (operand.llval, None)
623 };
624
625 let unsized_ty = cast_ty.builtin_deref(true, ty::NoPreference)
626 .expect("consts: unsizing got non-pointer target type").ty;
627 let ptr_ty = type_of::in_memory_type_of(self.ccx, unsized_ty).ptr_to();
628 let base = consts::ptrcast(base, ptr_ty);
629 let info = base::unsized_info(self.ccx, pointee_ty,
630 unsized_ty, old_info);
631
632 if old_info.is_none() {
633 let prev_const = self.ccx.const_unsized().borrow_mut()
634 .insert(base, operand.llval);
635 assert!(prev_const.is_none() || prev_const == Some(operand.llval));
636 }
637 assert_eq!(abi::FAT_PTR_ADDR, 0);
638 assert_eq!(abi::FAT_PTR_EXTRA, 1);
639 C_struct(self.ccx, &[base, info], false)
640 }
641 mir::CastKind::Misc if common::type_is_immediate(self.ccx, operand.ty) => {
642 debug_assert!(common::type_is_immediate(self.ccx, cast_ty));
643 let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
644 let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
645 let ll_t_out = type_of::immediate_type_of(self.ccx, cast_ty);
646 let llval = operand.llval;
647 let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in {
9e0c209e
SL
648 let l = self.ccx.layout_of(operand.ty);
649 adt::is_discr_signed(&l)
a7813a04
XL
650 } else {
651 operand.ty.is_signed()
652 };
653
654 unsafe {
655 match (r_t_in, r_t_out) {
656 (CastTy::Int(_), CastTy::Int(_)) => {
657 let s = signed as llvm::Bool;
658 llvm::LLVMConstIntCast(llval, ll_t_out.to_ref(), s)
659 }
660 (CastTy::Int(_), CastTy::Float) => {
661 if signed {
662 llvm::LLVMConstSIToFP(llval, ll_t_out.to_ref())
663 } else {
664 llvm::LLVMConstUIToFP(llval, ll_t_out.to_ref())
665 }
666 }
667 (CastTy::Float, CastTy::Float) => {
668 llvm::LLVMConstFPCast(llval, ll_t_out.to_ref())
669 }
670 (CastTy::Float, CastTy::Int(IntTy::I)) => {
671 llvm::LLVMConstFPToSI(llval, ll_t_out.to_ref())
672 }
673 (CastTy::Float, CastTy::Int(_)) => {
674 llvm::LLVMConstFPToUI(llval, ll_t_out.to_ref())
675 }
676 (CastTy::Ptr(_), CastTy::Ptr(_)) |
677 (CastTy::FnPtr, CastTy::Ptr(_)) |
678 (CastTy::RPtr(_), CastTy::Ptr(_)) => {
679 consts::ptrcast(llval, ll_t_out)
680 }
681 (CastTy::Int(_), CastTy::Ptr(_)) => {
682 llvm::LLVMConstIntToPtr(llval, ll_t_out.to_ref())
683 }
684 (CastTy::Ptr(_), CastTy::Int(_)) |
685 (CastTy::FnPtr, CastTy::Int(_)) => {
686 llvm::LLVMConstPtrToInt(llval, ll_t_out.to_ref())
687 }
688 _ => bug!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
689 }
690 }
691 }
692 mir::CastKind::Misc => { // Casts from a fat-ptr.
693 let ll_cast_ty = type_of::immediate_type_of(self.ccx, cast_ty);
694 let ll_from_ty = type_of::immediate_type_of(self.ccx, operand.ty);
32a655c1 695 if common::type_is_fat_ptr(self.ccx, operand.ty) {
a7813a04 696 let (data_ptr, meta_ptr) = operand.get_fat_ptr();
32a655c1 697 if common::type_is_fat_ptr(self.ccx, cast_ty) {
a7813a04
XL
698 let ll_cft = ll_cast_ty.field_types();
699 let ll_fft = ll_from_ty.field_types();
700 let data_cast = consts::ptrcast(data_ptr, ll_cft[0]);
701 assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
702 C_struct(self.ccx, &[data_cast, meta_ptr], false)
703 } else { // cast to thin-ptr
704 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
705 // pointer-cast of that pointer to desired pointer type.
706 consts::ptrcast(data_ptr, ll_cast_ty)
707 }
708 } else {
3157f602 709 bug!("Unexpected non-fat-pointer operand")
a7813a04
XL
710 }
711 }
712 };
713 Const::new(val, cast_ty)
714 }
715
716 mir::Rvalue::Ref(_, bk, ref lvalue) => {
717 let tr_lvalue = self.const_lvalue(lvalue, span)?;
718
719 let ty = tr_lvalue.ty;
3157f602 720 let ref_ty = tcx.mk_ref(tcx.mk_region(ty::ReErased),
a7813a04
XL
721 ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() });
722
723 let base = match tr_lvalue.base {
724 Base::Value(llval) => {
9e0c209e 725 // FIXME: may be wrong for &*(&simd_vec as &fmt::Debug)
32a655c1 726 let align = if self.ccx.shared().type_is_sized(ty) {
9e0c209e
SL
727 type_of::align_of(self.ccx, ty)
728 } else {
729 self.ccx.tcx().data_layout.pointer_align.abi() as machine::llalign
730 };
a7813a04
XL
731 if bk == mir::BorrowKind::Mut {
732 consts::addr_of_mut(self.ccx, llval, align, "ref_mut")
733 } else {
734 consts::addr_of(self.ccx, llval, align, "ref")
735 }
736 }
737 Base::Str(llval) |
738 Base::Static(llval) => llval
739 };
740
32a655c1 741 let ptr = if self.ccx.shared().type_is_sized(ty) {
a7813a04
XL
742 base
743 } else {
744 C_struct(self.ccx, &[base, tr_lvalue.llextra], false)
745 };
746 Const::new(ptr, ref_ty)
747 }
748
749 mir::Rvalue::Len(ref lvalue) => {
750 let tr_lvalue = self.const_lvalue(lvalue, span)?;
751 Const::new(tr_lvalue.len(self.ccx), tcx.types.usize)
752 }
753
754 mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
755 let lhs = self.const_operand(lhs, span)?;
756 let rhs = self.const_operand(rhs, span)?;
757 let ty = lhs.ty;
5bcae85e 758 let binop_ty = op.ty(tcx, lhs.ty, rhs.ty);
a7813a04 759 let (lhs, rhs) = (lhs.llval, rhs.llval);
3157f602
XL
760 Const::new(const_scalar_binop(op, lhs, rhs, ty), binop_ty)
761 }
a7813a04 762
3157f602
XL
763 mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
764 let lhs = self.const_operand(lhs, span)?;
765 let rhs = self.const_operand(rhs, span)?;
766 let ty = lhs.ty;
5bcae85e 767 let val_ty = op.ty(tcx, lhs.ty, rhs.ty);
8bb4bdeb 768 let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool], false);
3157f602
XL
769 let (lhs, rhs) = (lhs.llval, rhs.llval);
770 assert!(!ty.is_fp());
a7813a04 771
3157f602
XL
772 match const_scalar_checked_binop(tcx, op, lhs, rhs, ty) {
773 Some((llval, of)) => {
774 let llof = C_bool(self.ccx, of);
775 Const::new(C_struct(self.ccx, &[llval, llof], false), binop_ty)
a7813a04 776 }
3157f602
XL
777 None => {
778 span_bug!(span, "{:?} got non-integer operands: {:?} and {:?}",
779 rvalue, Value(lhs), Value(rhs));
780 }
781 }
a7813a04
XL
782 }
783
784 mir::Rvalue::UnaryOp(op, ref operand) => {
785 let operand = self.const_operand(operand, span)?;
786 let lloperand = operand.llval;
787 let llval = match op {
788 mir::UnOp::Not => {
789 unsafe {
790 llvm::LLVMConstNot(lloperand)
791 }
792 }
793 mir::UnOp::Neg => {
a7813a04
XL
794 let is_float = operand.ty.is_fp();
795 unsafe {
796 if is_float {
797 llvm::LLVMConstFNeg(lloperand)
798 } else {
799 llvm::LLVMConstNeg(lloperand)
800 }
801 }
802 }
803 };
804 Const::new(llval, operand.ty)
805 }
806
807 _ => span_bug!(span, "{:?} in constant", rvalue)
808 };
809
5bcae85e
SL
810 debug!("const_rvalue({:?}: {:?} @ {:?}) = {:?}", rvalue, dest_ty, span, val);
811
a7813a04
XL
812 Ok(val)
813 }
3157f602
XL
814
815}
816
9e0c209e
SL
817fn to_const_int(value: ValueRef, t: Ty, tcx: TyCtxt) -> Option<ConstInt> {
818 match t.sty {
32a655c1
SL
819 ty::TyInt(int_type) => const_to_opt_u128(value, true)
820 .and_then(|input| ConstInt::new_signed(input as i128, int_type,
821 tcx.sess.target.int_type)),
822 ty::TyUint(uint_type) => const_to_opt_u128(value, false)
823 .and_then(|input| ConstInt::new_unsigned(input, uint_type,
824 tcx.sess.target.uint_type)),
825 _ => None
826
9e0c209e
SL
827 }
828}
829
3157f602
XL
830pub fn const_scalar_binop(op: mir::BinOp,
831 lhs: ValueRef,
832 rhs: ValueRef,
833 input_ty: Ty) -> ValueRef {
834 assert!(!input_ty.is_simd());
835 let is_float = input_ty.is_fp();
836 let signed = input_ty.is_signed();
837
838 unsafe {
839 match op {
840 mir::BinOp::Add if is_float => llvm::LLVMConstFAdd(lhs, rhs),
841 mir::BinOp::Add => llvm::LLVMConstAdd(lhs, rhs),
842
843 mir::BinOp::Sub if is_float => llvm::LLVMConstFSub(lhs, rhs),
844 mir::BinOp::Sub => llvm::LLVMConstSub(lhs, rhs),
845
846 mir::BinOp::Mul if is_float => llvm::LLVMConstFMul(lhs, rhs),
847 mir::BinOp::Mul => llvm::LLVMConstMul(lhs, rhs),
848
849 mir::BinOp::Div if is_float => llvm::LLVMConstFDiv(lhs, rhs),
850 mir::BinOp::Div if signed => llvm::LLVMConstSDiv(lhs, rhs),
851 mir::BinOp::Div => llvm::LLVMConstUDiv(lhs, rhs),
852
853 mir::BinOp::Rem if is_float => llvm::LLVMConstFRem(lhs, rhs),
854 mir::BinOp::Rem if signed => llvm::LLVMConstSRem(lhs, rhs),
855 mir::BinOp::Rem => llvm::LLVMConstURem(lhs, rhs),
856
857 mir::BinOp::BitXor => llvm::LLVMConstXor(lhs, rhs),
858 mir::BinOp::BitAnd => llvm::LLVMConstAnd(lhs, rhs),
859 mir::BinOp::BitOr => llvm::LLVMConstOr(lhs, rhs),
860 mir::BinOp::Shl => {
861 let rhs = base::cast_shift_const_rhs(op.to_hir_binop(), lhs, rhs);
862 llvm::LLVMConstShl(lhs, rhs)
863 }
864 mir::BinOp::Shr => {
865 let rhs = base::cast_shift_const_rhs(op.to_hir_binop(), lhs, rhs);
866 if signed { llvm::LLVMConstAShr(lhs, rhs) }
867 else { llvm::LLVMConstLShr(lhs, rhs) }
868 }
869 mir::BinOp::Eq | mir::BinOp::Ne |
870 mir::BinOp::Lt | mir::BinOp::Le |
871 mir::BinOp::Gt | mir::BinOp::Ge => {
872 if is_float {
873 let cmp = base::bin_op_to_fcmp_predicate(op.to_hir_binop());
5bcae85e 874 llvm::LLVMConstFCmp(cmp, lhs, rhs)
3157f602
XL
875 } else {
876 let cmp = base::bin_op_to_icmp_predicate(op.to_hir_binop(),
877 signed);
5bcae85e 878 llvm::LLVMConstICmp(cmp, lhs, rhs)
3157f602
XL
879 }
880 }
881 }
882 }
883}
884
885pub fn const_scalar_checked_binop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
886 op: mir::BinOp,
887 lllhs: ValueRef,
888 llrhs: ValueRef,
889 input_ty: Ty<'tcx>)
890 -> Option<(ValueRef, bool)> {
891 if let (Some(lhs), Some(rhs)) = (to_const_int(lllhs, input_ty, tcx),
892 to_const_int(llrhs, input_ty, tcx)) {
893 let result = match op {
894 mir::BinOp::Add => lhs + rhs,
895 mir::BinOp::Sub => lhs - rhs,
896 mir::BinOp::Mul => lhs * rhs,
897 mir::BinOp::Shl => lhs << rhs,
898 mir::BinOp::Shr => lhs >> rhs,
899 _ => {
900 bug!("Operator `{:?}` is not a checkable operator", op)
901 }
902 };
903
904 let of = match result {
905 Ok(_) => false,
906 Err(ConstMathErr::Overflow(_)) |
907 Err(ConstMathErr::ShiftNegative) => true,
908 Err(err) => {
909 bug!("Operator `{:?}` on `{:?}` and `{:?}` errored: {}",
910 op, lhs, rhs, err.description());
911 }
912 };
913
914 Some((const_scalar_binop(op, lllhs, llrhs, input_ty), of))
915 } else {
916 None
917 }
a7813a04
XL
918}
919
32a655c1 920impl<'a, 'tcx> MirContext<'a, 'tcx> {
54a0048b 921 pub fn trans_constant(&mut self,
32a655c1 922 bcx: &Builder<'a, 'tcx>,
54a0048b 923 constant: &mir::Constant<'tcx>)
a7813a04 924 -> Const<'tcx>
54a0048b 925 {
5bcae85e 926 debug!("trans_constant({:?})", constant);
32a655c1 927 let ty = self.monomorphize(&constant.ty);
a7813a04 928 let result = match constant.literal.clone() {
54a0048b
SL
929 mir::Literal::Item { def_id, substs } => {
930 // Shortcut for zero-sized types, including function item
a7813a04 931 // types, which would not work with MirConstContext.
32a655c1
SL
932 if common::type_is_zero_size(bcx.ccx, ty) {
933 let llty = type_of::type_of(bcx.ccx, ty);
a7813a04 934 return Const::new(C_null(llty), ty);
54a0048b
SL
935 }
936
32a655c1 937 let substs = self.monomorphize(&substs);
a7813a04 938 let instance = Instance::new(def_id, substs);
32a655c1 939 MirConstContext::trans_def(bcx.ccx, instance, IndexVec::new())
a7813a04
XL
940 }
941 mir::Literal::Promoted { index } => {
942 let mir = &self.mir.promoted[index];
32a655c1 943 MirConstContext::new(bcx.ccx, mir, self.param_substs, IndexVec::new()).trans()
a7813a04
XL
944 }
945 mir::Literal::Value { value } => {
32a655c1 946 Ok(Const::from_constval(bcx.ccx, value, ty))
54a0048b 947 }
a7813a04
XL
948 };
949
9e0c209e
SL
950 let result = result.unwrap_or_else(|_| {
951 // We've errored, so we don't have to produce working code.
32a655c1 952 let llty = type_of::type_of(bcx.ccx, ty);
9e0c209e
SL
953 Const::new(C_undef(llty), ty)
954 });
5bcae85e
SL
955
956 debug!("trans_constant({:?}) = {:?}", constant, result);
957 result
54a0048b
SL
958 }
959}
a7813a04
XL
960
961
8bb4bdeb
XL
962pub fn trans_static_initializer<'a, 'tcx>(
963 ccx: &CrateContext<'a, 'tcx>,
964 def_id: DefId)
965 -> Result<ValueRef, ConstEvalErr<'tcx>>
966{
a7813a04 967 let instance = Instance::mono(ccx.shared(), def_id);
3157f602 968 MirConstContext::trans_def(ccx, instance, IndexVec::new()).map(|c| c.llval)
a7813a04 969}
32a655c1
SL
970
971/// Construct a constant value, suitable for initializing a
972/// GlobalVariable, given a case and constant values for its fields.
973/// Note that this may have a different LLVM type (and different
974/// alignment!) from the representation's `type_of`, so it needs a
975/// pointer cast before use.
976///
977/// The LLVM type system does not directly support unions, and only
978/// pointers can be bitcast, so a constant (and, by extension, the
979/// GlobalVariable initialized by it) will have a type that can vary
980/// depending on which case of an enum it is.
981///
982/// To understand the alignment situation, consider `enum E { V64(u64),
983/// V32(u32, u32) }` on Windows. The type has 8-byte alignment to
984/// accommodate the u64, but `V32(x, y)` would have LLVM type `{i32,
985/// i32, i32}`, which is 4-byte aligned.
986///
987/// Currently the returned value has the same size as the type, but
988/// this could be changed in the future to avoid allocating unnecessary
989/// space after values of shorter-than-maximum cases.
990fn trans_const<'a, 'tcx>(
991 ccx: &CrateContext<'a, 'tcx>,
992 t: Ty<'tcx>,
993 kind: &mir::AggregateKind,
994 vals: &[ValueRef]
995) -> ValueRef {
996 let l = ccx.layout_of(t);
997 let dl = &ccx.tcx().data_layout;
998 let variant_index = match *kind {
999 mir::AggregateKind::Adt(_, index, _, _) => index,
1000 _ => 0,
1001 };
1002 match *l {
1003 layout::CEnum { discr: d, min, max, .. } => {
1004 let discr = match *kind {
1005 mir::AggregateKind::Adt(adt_def, _, _, _) => {
8bb4bdeb 1006 Disr::for_variant(ccx.tcx(), adt_def, variant_index)
32a655c1
SL
1007 },
1008 _ => Disr(0),
1009 };
1010 assert_eq!(vals.len(), 0);
1011 adt::assert_discr_in_range(Disr(min), Disr(max), discr);
1012 C_integral(Type::from_integer(ccx, d), discr.0, true)
1013 }
1014 layout::General { discr: d, ref variants, .. } => {
1015 let variant = &variants[variant_index];
1016 let lldiscr = C_integral(Type::from_integer(ccx, d), variant_index as u64, true);
1017 let mut vals_with_discr = vec![lldiscr];
1018 vals_with_discr.extend_from_slice(vals);
1019 let mut contents = build_const_struct(ccx, &variant, &vals_with_discr[..]);
1020 let needed_padding = l.size(dl).bytes() - variant.stride().bytes();
1021 if needed_padding > 0 {
1022 contents.push(padding(ccx, needed_padding));
1023 }
1024 C_struct(ccx, &contents[..], false)
1025 }
1026 layout::UntaggedUnion { ref variants, .. }=> {
1027 assert_eq!(variant_index, 0);
1028 let contents = build_const_union(ccx, variants, vals[0]);
1029 C_struct(ccx, &contents, variants.packed)
1030 }
1031 layout::Univariant { ref variant, .. } => {
1032 assert_eq!(variant_index, 0);
1033 let contents = build_const_struct(ccx, &variant, vals);
1034 C_struct(ccx, &contents[..], variant.packed)
1035 }
1036 layout::Vector { .. } => {
1037 C_vector(vals)
1038 }
1039 layout::RawNullablePointer { nndiscr, .. } => {
1040 let nnty = adt::compute_fields(ccx, t, nndiscr as usize, false)[0];
1041 if variant_index as u64 == nndiscr {
1042 assert_eq!(vals.len(), 1);
1043 vals[0]
1044 } else {
1045 C_null(type_of::sizing_type_of(ccx, nnty))
1046 }
1047 }
1048 layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
1049 if variant_index as u64 == nndiscr {
1050 C_struct(ccx, &build_const_struct(ccx, &nonnull, vals), false)
1051 } else {
1052 let fields = adt::compute_fields(ccx, t, nndiscr as usize, false);
1053 let vals = fields.iter().map(|&ty| {
1054 // Always use null even if it's not the `discrfield`th
1055 // field; see #8506.
1056 C_null(type_of::sizing_type_of(ccx, ty))
1057 }).collect::<Vec<ValueRef>>();
1058 C_struct(ccx, &build_const_struct(ccx, &nonnull, &vals[..]), false)
1059 }
1060 }
1061 _ => bug!("trans_const: cannot handle type {} repreented as {:#?}", t, l)
1062 }
1063}
1064
1065/// Building structs is a little complicated, because we might need to
1066/// insert padding if a field's value is less aligned than its type.
1067///
1068/// Continuing the example from `trans_const`, a value of type `(u32,
1069/// E)` should have the `E` at offset 8, but if that field's
1070/// initializer is 4-byte aligned then simply translating the tuple as
1071/// a two-element struct will locate it at offset 4, and accesses to it
1072/// will read the wrong memory.
1073fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1074 st: &layout::Struct,
1075 vals: &[ValueRef])
1076 -> Vec<ValueRef> {
1077 assert_eq!(vals.len(), st.offsets.len());
1078
1079 if vals.len() == 0 {
1080 return Vec::new();
1081 }
1082
1083 // offset of current value
1084 let mut offset = 0;
1085 let mut cfields = Vec::new();
1086 cfields.reserve(st.offsets.len()*2);
1087
1088 let parts = st.field_index_by_increasing_offset().map(|i| {
1089 (&vals[i], st.offsets[i].bytes())
1090 });
1091 for (&val, target_offset) in parts {
1092 if offset < target_offset {
1093 cfields.push(padding(ccx, target_offset - offset));
1094 offset = target_offset;
1095 }
1096 assert!(!is_undef(val));
1097 cfields.push(val);
1098 offset += machine::llsize_of_alloc(ccx, val_ty(val));
1099 }
1100
1101 if offset < st.stride().bytes() {
1102 cfields.push(padding(ccx, st.stride().bytes() - offset));
1103 }
1104
1105 cfields
1106}
1107
1108fn build_const_union<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1109 un: &layout::Union,
1110 field_val: ValueRef)
1111 -> Vec<ValueRef> {
1112 let mut cfields = vec![field_val];
1113
1114 let offset = machine::llsize_of_alloc(ccx, val_ty(field_val));
1115 let size = un.stride().bytes();
1116 if offset != size {
1117 cfields.push(padding(ccx, size - offset));
1118 }
1119
1120 cfields
1121}
1122
1123fn padding(ccx: &CrateContext, size: u64) -> ValueRef {
1124 C_undef(Type::array(&Type::i8(ccx), size))
1125}