diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 95d963a36e3aa..63d9bac1cd7aa 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1073,8 +1073,10 @@ pub mod funcs { // Omitted: putc, putchar (might be macros). unsafe fn puts(s: *c_char) -> c_int; unsafe fn ungetc(c: c_int, stream: *FILE) -> c_int; + #[fast_ffi] unsafe fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *FILE) -> size_t; + #[fast_ffi] unsafe fn fwrite(ptr: *c_void, size: size_t, nobj: size_t, stream: *FILE) -> size_t; unsafe fn fseek(stream: *FILE, offset: c_long, @@ -1108,9 +1110,13 @@ pub mod funcs { -> c_long; unsafe fn strtoul(s: *c_char, endp: **c_char, base: c_int) -> c_ulong; + #[fast_ffi] unsafe fn calloc(nobj: size_t, size: size_t) -> *c_void; + #[fast_ffi] unsafe fn malloc(size: size_t) -> *c_void; + #[fast_ffi] unsafe fn realloc(p: *c_void, size: size_t) -> *c_void; + #[fast_ffi] unsafe fn free(p: *c_void); unsafe fn abort() -> !; unsafe fn exit(status: c_int) -> !; @@ -1304,6 +1310,7 @@ pub mod funcs { textmode: c_int) -> c_int; #[link_name = "_read"] + #[fast_ffi] unsafe fn read(fd: c_int, buf: *mut c_void, count: c_uint) -> c_int; @@ -1314,6 +1321,7 @@ pub mod funcs { unsafe fn unlink(c: *c_char) -> c_int; #[link_name = "_write"] + #[fast_ffi] unsafe fn write(fd: c_int, buf: *c_void, count: c_uint) -> c_int; } @@ -1466,6 +1474,7 @@ pub mod funcs { unsafe fn pathconf(path: *c_char, name: c_int) -> c_long; unsafe fn pause() -> c_int; unsafe fn pipe(fds: *mut c_int) -> c_int; + #[fast_ffi] unsafe fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; unsafe fn rmdir(path: *c_char) -> c_int; @@ -1478,6 +1487,7 @@ pub mod funcs { unsafe fn tcgetpgrp(fd: c_int) -> pid_t; unsafe fn ttyname(fd: c_int) -> *c_char; unsafe fn unlink(c: *c_char) -> c_int; + #[fast_ffi] unsafe fn write(fd: c_int, buf: *c_void, count: size_t) -> ssize_t; } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 2201836c72410..bf64ff38da025 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -66,6 +66,15 @@ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str { return unsafe { raw::from_bytes_with_null(vv) }; } +pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str { + unsafe { + assert!(is_utf8(vector)); + let (ptr, len): (*u8, uint) = ::cast::transmute(vector); + let string: &'a str = ::cast::transmute((ptr, len + 1)); + string + } +} + /// Copy a slice into a new unique str pub fn from_slice(s: &str) -> ~str { unsafe { raw::slice_bytes_owned(s, 0, len(s)) } diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index dad990c0f97cf..8298c903d52ad 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -35,6 +35,14 @@ pub mod rustrt { #[rust_stack] unsafe fn rust_upcall_free(ptr: *c_char); + + #[fast_ffi] + unsafe fn rust_upcall_malloc_noswitch(td: *c_char, + size: uintptr_t) + -> *c_char; + + #[fast_ffi] + unsafe fn rust_upcall_free_noswitch(ptr: *c_char); } } @@ -81,7 +89,7 @@ pub unsafe fn exchange_free(ptr: *c_char) { #[lang="malloc"] #[inline(always)] pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { - return rustrt::rust_upcall_malloc(td, size); + return rustrt::rust_upcall_malloc_noswitch(td, size); } // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from @@ -90,7 +98,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { #[lang="free"] #[inline(always)] pub unsafe fn local_free(ptr: *c_char) { - rustrt::rust_upcall_free(ptr); + rustrt::rust_upcall_free_noswitch(ptr); } #[lang="borrow_as_imm"] diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 5b06591f9ecc8..56ee6bf0e5937 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -39,9 +39,11 @@ pub mod rustrt { pub extern { // These names are terrible. reserve_shared applies // to ~[] and reserve_shared_actual applies to @[]. + #[fast_ffi] unsafe fn vec_reserve_shared(++t: *sys::TypeDesc, ++v: **raw::VecRepr, ++n: libc::size_t); + #[fast_ffi] unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc, ++v: **raw::VecRepr, ++n: libc::size_t); diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index d725b70003754..72b0a3207f732 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -172,10 +172,13 @@ pub enum compile_upto { // For continuing compilation after a parsed crate has been // modified -pub fn compile_rest(sess: Session, cfg: ast::crate_cfg, - upto: compile_upto, outputs: Option<@OutputFilenames>, +#[fixed_stack_segment] +pub fn compile_rest(sess: Session, + cfg: ast::crate_cfg, + upto: compile_upto, + outputs: Option<@OutputFilenames>, curr: Option<@ast::crate>) - -> (@ast::crate, Option) { + -> (@ast::crate, Option) { let time_passes = sess.time_passes(); let mut crate = curr.get(); diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index b6d3fce7e7546..9783b84ff14d5 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -236,438 +236,624 @@ pub mod llvm { #[abi = "cdecl"] pub extern { /* Create and destroy contexts. */ + #[fast_ffi] pub unsafe fn LLVMContextCreate() -> ContextRef; + #[fast_ffi] pub unsafe fn LLVMGetGlobalContext() -> ContextRef; + #[fast_ffi] pub unsafe fn LLVMContextDispose(C: ContextRef); + #[fast_ffi] pub unsafe fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *c_char, SLen: c_uint) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint; /* Create and destroy modules. */ + #[fast_ffi] pub unsafe fn LLVMModuleCreateWithNameInContext(ModuleID: *c_char, C: ContextRef) -> ModuleRef; + #[fast_ffi] pub unsafe fn LLVMDisposeModule(M: ModuleRef); /** Data layout. See Module::getDataLayout. */ + #[fast_ffi] pub unsafe fn LLVMGetDataLayout(M: ModuleRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetDataLayout(M: ModuleRef, Triple: *c_char); /** Target triple. See Module::getTargetTriple. */ + #[fast_ffi] pub unsafe fn LLVMGetTarget(M: ModuleRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetTarget(M: ModuleRef, Triple: *c_char); /** See Module::dump. */ + #[fast_ffi] pub unsafe fn LLVMDumpModule(M: ModuleRef); /** See Module::setModuleInlineAsm. */ + #[fast_ffi] pub unsafe fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *c_char); /** See llvm::LLVMTypeKind::getTypeID. */ pub unsafe fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind; /** See llvm::LLVMType::getContext. */ + #[fast_ffi] pub unsafe fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef; /* Operations on integer types */ + #[fast_ffi] pub unsafe fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt1Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt8Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt16Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt32Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt64Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMIntType(NumBits: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint; /* Operations on real types */ + #[fast_ffi] pub unsafe fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMFloatType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMDoubleType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMX86FP80Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMFP128Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMPPCFP128Type() -> TypeRef; /* Operations on function types */ + #[fast_ffi] pub unsafe fn LLVMFunctionType(ReturnType: TypeRef, ParamTypes: *TypeRef, ParamCount: c_uint, IsVarArg: Bool) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *TypeRef); /* Operations on struct types */ + #[fast_ffi] pub unsafe fn LLVMStructTypeInContext(C: ContextRef, ElementTypes: *TypeRef, ElementCount: c_uint, Packed: Bool) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMStructType(ElementTypes: *TypeRef, ElementCount: c_uint, Packed: Bool) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetStructElementTypes(StructTy: TypeRef, Dest: *mut TypeRef); + #[fast_ffi] pub unsafe fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool; /* Operations on array, pointer, and vector types (sequence types) */ + #[fast_ffi] pub unsafe fn LLVMArrayType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetElementType(Ty: TypeRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint; /* Operations on other types */ + #[fast_ffi] pub unsafe fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMVoidType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMLabelType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMMetadataType() -> TypeRef; /* Operations on all values */ + #[fast_ffi] pub unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetValueName(Val: ValueRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetValueName(Val: ValueRef, Name: *c_char); + #[fast_ffi] pub unsafe fn LLVMDumpValue(Val: ValueRef); + #[fast_ffi] pub unsafe fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef); + #[fast_ffi] pub unsafe fn LLVMHasMetadata(Val: ValueRef) -> c_int; + #[fast_ffi] pub unsafe fn LLVMGetMetadata(Val: ValueRef, KindID: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef); /* Operations on Uses */ + #[fast_ffi] pub unsafe fn LLVMGetFirstUse(Val: ValueRef) -> UseRef; + #[fast_ffi] pub unsafe fn LLVMGetNextUse(U: UseRef) -> UseRef; + #[fast_ffi] pub unsafe fn LLVMGetUser(U: UseRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetUsedValue(U: UseRef) -> ValueRef; /* Operations on Users */ + #[fast_ffi] pub unsafe fn LLVMGetNumOperands(Val: ValueRef) -> c_int; + #[fast_ffi] pub unsafe fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef); /* Operations on constants of any type */ + #[fast_ffi] pub unsafe fn LLVMConstNull(Ty: TypeRef) -> ValueRef; /* all zeroes */ + #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; /* only for int/vector */ + #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMIsConstant(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMIsNull(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMIsUndef(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef; /* Operations on metadata */ + #[fast_ffi] pub unsafe fn LLVMMDStringInContext(C: ContextRef, Str: *c_char, SLen: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMMDNodeInContext(C: ContextRef, Vals: *ValueRef, Count: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char, Val: ValueRef); /* Operations on scalar constants */ + #[fast_ffi] pub unsafe fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntOfString(IntTy: TypeRef, Text: *c_char, Radix: u8) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntOfStringAndSize(IntTy: TypeRef, Text: *c_char, SLen: c_uint, Radix: u8) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstRealOfString(RealTy: TypeRef, Text: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstRealOfStringAndSize(RealTy: TypeRef, Text: *c_char, SLen: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong; + #[fast_ffi] pub unsafe fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong; /* Operations on composite constants */ + #[fast_ffi] pub unsafe fn LLVMConstStringInContext(C: ContextRef, Str: *c_char, Length: c_uint, DontNullTerminate: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstStructInContext(C: ContextRef, ConstantVals: *ValueRef, Count: c_uint, Packed: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstString(Str: *c_char, Length: c_uint, DontNullTerminate: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstArray(ElementTy: TypeRef, ConstantVals: *ValueRef, Length: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstStruct(ConstantVals: *ValueRef, Count: c_uint, Packed: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef, Size: c_uint) -> ValueRef; /* Constant expressions */ + #[fast_ffi] pub unsafe fn LLVMAlignOf(Ty: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSizeOf(Ty: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstExactSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstGEP(ConstantVal: ValueRef, ConstantIndices: *ValueRef, NumIndices: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: *ValueRef, NumIndices: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef, isSigned: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSelect(ConstantCondition: ValueRef, ConstantIfTrue: ValueRef, ConstantIfFalse: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstExtractElement(VectorConstant: ValueRef, IndexConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInsertElement(VectorConstant: ValueRef, ElementValueConstant: ValueRef, IndexConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstShuffleVector(VectorAConstant: ValueRef, VectorBConstant: ValueRef, MaskConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstExtractValue(AggConstant: ValueRef, IdxList: *c_uint, NumIdx: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInsertValue(AggConstant: ValueRef, ElementValueConstant: ValueRef, IdxList: *c_uint, NumIdx: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInlineAsm(Ty: TypeRef, AsmString: *c_char, Constraints: *c_char, HasSideEffects: Bool, IsAlignStack: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef; /* Operations on global variables, functions, and aliases (globals) */ + #[fast_ffi] pub unsafe fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef; + #[fast_ffi] pub unsafe fn LLVMIsDeclaration(Global: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMGetLinkage(Global: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetLinkage(Global: ValueRef, Link: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetSection(Global: ValueRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetSection(Global: ValueRef, Section: *c_char); + #[fast_ffi] pub unsafe fn LLVMGetVisibility(Global: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetAlignment(Global: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint); /* Operations on global variables */ + #[fast_ffi] pub unsafe fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMAddGlobalInAddressSpace(M: ModuleRef, Ty: TypeRef, Name: *c_char, AddressSpace: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNamedGlobal(M: ModuleRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMDeleteGlobal(GlobalVar: ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef); + #[fast_ffi] pub unsafe fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool); + #[fast_ffi] pub unsafe fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool); /* Operations on aliases */ + #[fast_ffi] pub unsafe fn LLVMAddAlias(M: ModuleRef, Ty: TypeRef, Aliasee: ValueRef, @@ -675,161 +861,242 @@ pub mod llvm { -> ValueRef; /* Operations on functions */ + #[fast_ffi] pub unsafe fn LLVMAddFunction(M: ModuleRef, Name: *c_char, FunctionTy: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNamedFunction(M: ModuleRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMDeleteFunction(Fn: ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetOrInsertFunction(M: ModuleRef, Name: *c_char, FunctionTy: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetGC(Fn: ValueRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetGC(Fn: ValueRef, Name: *c_char); + #[fast_ffi] pub unsafe fn LLVMAddFunctionAttr(Fn: ValueRef, - PA: c_ulonglong, - HighPA: c_ulonglong); + PA: c_uint, + HighPA: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong; + #[fast_ffi] pub unsafe fn LLVMRemoveFunctionAttr(Fn: ValueRef, PA: c_ulonglong, HighPA: c_ulonglong); /* Operations on parameters */ + #[fast_ffi] pub unsafe fn LLVMCountParams(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetParams(Fn: ValueRef, Params: *ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint); + #[fast_ffi] pub unsafe fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetAttribute(Arg: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint); /* Operations on basic blocks */ + #[fast_ffi] pub unsafe fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMInsertBasicBlockInContext(C: ContextRef, BB: BasicBlockRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMAppendBasicBlock(Fn: ValueRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef); /* Operations on instructions */ + #[fast_ffi] pub unsafe fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef; /* Operations on call sites */ + #[fast_ffi] pub unsafe fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMAddInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); + #[fast_ffi] pub unsafe fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); + #[fast_ffi] pub unsafe fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: c_uint, align: c_uint); /* Operations on call instructions (only) */ + #[fast_ffi] pub unsafe fn LLVMIsTailCall(CallInst: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool); /* Operations on phi nodes */ + #[fast_ffi] pub unsafe fn LLVMAddIncoming(PhiNode: ValueRef, IncomingValues: *ValueRef, IncomingBlocks: *BasicBlockRef, Count: c_uint); + #[fast_ffi] pub unsafe fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetIncomingBlock(PhiNode: ValueRef, Index: c_uint) -> BasicBlockRef; /* Instruction builders */ + #[fast_ffi] pub unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef; + #[fast_ffi] pub unsafe fn LLVMCreateBuilder() -> BuilderRef; + #[fast_ffi] pub unsafe fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef); + #[fast_ffi] pub unsafe fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef); + #[fast_ffi] pub unsafe fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef); + #[fast_ffi] pub unsafe fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMClearInsertionPosition(Builder: BuilderRef); + #[fast_ffi] pub unsafe fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef); + #[fast_ffi] pub unsafe fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef, Instr: ValueRef, Name: *c_char); + #[fast_ffi] pub unsafe fn LLVMDisposeBuilder(Builder: BuilderRef); /* Metadata */ + #[fast_ffi] pub unsafe fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef); /* Terminators */ + #[fast_ffi] pub unsafe fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *ValueRef, N: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildCondBr(B: BuilderRef, If: ValueRef, Then: BasicBlockRef, Else: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSwitch(B: BuilderRef, V: ValueRef, Else: BasicBlockRef, NumCases: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef, NumDests: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInvoke(B: BuilderRef, Fn: ValueRef, Args: *ValueRef, @@ -837,367 +1104,447 @@ pub mod llvm { Then: BasicBlockRef, Catch: BasicBlockRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildLandingPad(B: BuilderRef, Ty: TypeRef, PersFn: ValueRef, NumClauses: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef; /* Add a case to the switch instruction */ + #[fast_ffi] pub unsafe fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef); /* Add a destination to the indirectbr instruction */ + #[fast_ffi] pub unsafe fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef); /* Add a clause to the landing pad instruction */ + #[fast_ffi] pub unsafe fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef); /* Set the cleanup on a landing pad instruction */ + #[fast_ffi] pub unsafe fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool); /* Arithmetic */ + #[fast_ffi] pub unsafe fn LLVMBuildAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildUDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildExactSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildURem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildShl(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildLShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAnd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildOr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildXor(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildBinOp(B: BuilderRef, Op: Opcode, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; /* Memory */ + #[fast_ffi] pub unsafe fn LLVMBuildMalloc(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildArrayMalloc(B: BuilderRef, Ty: TypeRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildArrayAlloca(B: BuilderRef, Ty: TypeRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildGEP(B: BuilderRef, Pointer: ValueRef, Indices: *ValueRef, NumIndices: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInBoundsGEP(B: BuilderRef, Pointer: ValueRef, Indices: *ValueRef, NumIndices: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildStructGEP(B: BuilderRef, Pointer: ValueRef, Idx: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildGlobalString(B: BuilderRef, Str: *c_char, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildGlobalStringPtr(B: BuilderRef, Str: *c_char, Name: *c_char) -> ValueRef; /* Casts */ + #[fast_ffi] pub unsafe fn LLVMBuildTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildZExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPToUI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPToSI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildUIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildPtrToInt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIntToPtr(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildZExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildTruncOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildCast(B: BuilderRef, Op: Opcode, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildPointerCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIntCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; /* Comparisons */ + #[fast_ffi] pub unsafe fn LLVMBuildICmp(B: BuilderRef, Op: c_uint, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFCmp(B: BuilderRef, Op: c_uint, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; /* Miscellaneous instructions */ + #[fast_ffi] pub unsafe fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: *ValueRef, NumArgs: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSelect(B: BuilderRef, If: ValueRef, Then: ValueRef, Else: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildVAArg(B: BuilderRef, list: ValueRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildExtractElement(B: BuilderRef, VecVal: ValueRef, Index: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInsertElement(B: BuilderRef, VecVal: ValueRef, EltVal: ValueRef, Index: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildShuffleVector(B: BuilderRef, V1: ValueRef, V2: ValueRef, Mask: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildExtractValue(B: BuilderRef, AggVal: ValueRef, Index: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInsertValue(B: BuilderRef, AggVal: ValueRef, EltVal: ValueRef, @@ -1205,14 +1552,17 @@ pub mod llvm { Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, @@ -1227,155 +1577,227 @@ pub mod llvm { ++Order: AtomicOrdering) -> ValueRef; /* Selected entries from the downcasts. */ + #[fast_ffi] pub unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef; /** Writes a module to the specified path. Returns 0 on success. */ + #[fast_ffi] pub unsafe fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *c_char) -> c_int; /** Creates target data from a target layout string. */ + #[fast_ffi] pub unsafe fn LLVMCreateTargetData(StringRep: *c_char) -> TargetDataRef; /** Adds the target data to the given pass manager. The pass manager references the target data only weakly. */ + #[fast_ffi] pub unsafe fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef); /** Number of bytes clobbered when doing a Store to *T. */ + #[fast_ffi] pub unsafe fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong; /** Number of bytes clobbered when doing a Store to *T. */ + #[fast_ffi] pub unsafe fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong; /** Distance between successive elements in an array of T. Includes ABI padding. */ + #[fast_ffi] pub unsafe fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** Returns the preferred alignment of a type. */ + #[fast_ffi] pub unsafe fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** Returns the minimum alignment of a type. */ + #[fast_ffi] pub unsafe fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** * Returns the minimum alignment of a type when part of a call frame. */ + #[fast_ffi] pub unsafe fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** Disposes target data. */ + #[fast_ffi] pub unsafe fn LLVMDisposeTargetData(TD: TargetDataRef); /** Creates a pass manager. */ + #[fast_ffi] pub unsafe fn LLVMCreatePassManager() -> PassManagerRef; /** Disposes a pass manager. */ + #[fast_ffi] pub unsafe fn LLVMDisposePassManager(PM: PassManagerRef); /** Runs a pass manager on a module. */ + #[fast_ffi] pub unsafe fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool; /** Adds a verification pass. */ + #[fast_ffi] pub unsafe fn LLVMAddVerifierPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddIPSCCPPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddInstructionCombiningPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddCFGSimplificationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddFunctionInliningPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddFunctionAttrsPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddJumpThreadingPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddConstantPropagationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddReassociatePass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopRotatePass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLICMPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopUnswitchPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopDeletionPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopUnrollPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddGVNPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddMemCpyOptPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddSCCPPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddConstantMergePass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddArgumentPromotionPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddTailCallEliminationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddAggressiveDCEPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddGlobalDCEPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddPruneEHPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopIdiomPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddEarlyCSEPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef; + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetOptLevel( PMB: PassManagerBuilderRef, OptimizationLevel: c_uint); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetSizeLevel( PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetDisableUnitAtATime( PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetDisableUnrollLoops( PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls (PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderUseInlinerWithThreshold (PMB: PassManagerBuilderRef, threshold: c_uint); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderPopulateModulePassManager (PMB: PassManagerBuilderRef, PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderPopulateFunctionPassManager (PMB: PassManagerBuilderRef, PM: PassManagerRef); /** Destroys a memory buffer. */ + #[fast_ffi] pub unsafe fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef); /* Stuff that's in rustllvm/ because it's not upstream yet. */ /** Opens an object file. */ + #[fast_ffi] pub unsafe fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef; /** Closes an object file. */ + #[fast_ffi] pub unsafe fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef); /** Enumerates the sections in an object file. */ + #[fast_ffi] pub unsafe fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef; /** Destroys a section iterator. */ + #[fast_ffi] pub unsafe fn LLVMDisposeSectionIterator(SI: SectionIteratorRef); /** Returns true if the section iterator is at the end of the section list: */ + #[fast_ffi] pub unsafe fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef, SI: SectionIteratorRef) -> Bool; /** Moves the section iterator to point to the next section. */ + #[fast_ffi] pub unsafe fn LLVMMoveToNextSection(SI: SectionIteratorRef); /** Returns the current section name. */ + #[fast_ffi] pub unsafe fn LLVMGetSectionName(SI: SectionIteratorRef) -> *c_char; /** Returns the current section size. */ + #[fast_ffi] pub unsafe fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong; /** Returns the current section contents as a string buffer. */ + #[fast_ffi] pub unsafe fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *c_char; /** Reads the given file and returns it as a memory buffer. Use LLVMDisposeMemoryBuffer() to get rid of it. */ + #[fast_ffi] pub unsafe fn LLVMRustCreateMemoryBufferWithContentsOfFile( Path: *c_char) -> MemoryBufferRef; + #[fast_ffi] pub unsafe fn LLVMRustWriteOutputFile(PM: PassManagerRef, M: ModuleRef, Triple: *c_char, @@ -1389,17 +1811,21 @@ pub mod llvm { /** Returns a string describing the last error caused by an LLVMRust* call. */ + #[fast_ffi] pub unsafe fn LLVMRustGetLastError() -> *c_char; /** Prepare the JIT. Returns a memory manager that can load crates. */ + #[fast_ffi] pub unsafe fn LLVMRustPrepareJIT(__morestack: *()) -> *(); /** Load a crate into the memory manager. */ + #[fast_ffi] pub unsafe fn LLVMRustLoadCrate(MM: *(), Filename: *c_char) -> bool; /** Execute the JIT engine. */ + #[fast_ffi] pub unsafe fn LLVMRustExecuteJIT(MM: *(), PM: PassManagerRef, M: ModuleRef, @@ -1407,40 +1833,50 @@ pub mod llvm { EnableSegmentedStacks: bool) -> *(); /** Parses the bitcode in the given memory buffer. */ + #[fast_ffi] pub unsafe fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef; /** Parses LLVM asm in the given file */ + #[fast_ffi] pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char) -> ModuleRef; + #[fast_ffi] pub unsafe fn LLVMRustAddPrintModulePass(PM: PassManagerRef, M: ModuleRef, Output: *c_char); /** Turn on LLVM pass-timing. */ + #[fast_ffi] pub unsafe fn LLVMRustEnableTimePasses(); /// Print the pass timings since static dtors aren't picking them up. + #[fast_ffi] pub unsafe fn LLVMRustPrintPassTimings(); + #[fast_ffi] pub unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMStructSetBody(StructTy: TypeRef, ElementTypes: *TypeRef, ElementCount: c_uint, Packed: Bool); + #[fast_ffi] pub unsafe fn LLVMConstNamedStruct(S: TypeRef, ConstantVals: *ValueRef, Count: c_uint) -> ValueRef; /** Enables LLVM debug output. */ + #[fast_ffi] pub unsafe fn LLVMSetDebug(Enabled: c_int); /** Prepares inline assembly. */ + #[fast_ffi] pub unsafe fn LLVMInlineAsm(Ty: TypeRef, AsmString: *c_char, Constraints: *c_char, SideEffects: Bool, AlignStack: Bool, Dialect: c_uint) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 472b455b73531..248d847f89dae 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -37,7 +37,7 @@ use std::serialize::Decodable; use syntax::ast_map; use syntax::attr; use syntax::diagnostic::span_handler; -use syntax::parse::token::{ident_interner, special_idents}; +use syntax::parse::token::{StringRef, ident_interner, special_idents}; use syntax::print::pprust; use syntax::{ast, ast_util}; use syntax::codemap; @@ -249,12 +249,7 @@ fn doc_transformed_self_ty(doc: ebml::Doc, pub fn item_type(item_id: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { - let t = doc_type(item, tcx, cdata); - if family_names_type(item_family(item)) { - ty::mk_with_id(tcx, t, item_id) - } else { - t - } + doc_type(item, tcx, cdata) } fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef { @@ -327,7 +322,13 @@ fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path { fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { let name = reader::get_doc(item, tag_paths_data_name); - intr.intern(@str::from_bytes(reader::doc_data(name))) + do reader::with_doc_data(name) |data| { + let string = str::from_bytes_slice(data); + match intr.find_equiv(&StringRef(string)) { + None => intr.intern(@(string.to_owned())), + Some(val) => val, + } + } } fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 8f75f1bd4c2c8..96a49bf1d095f 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -379,9 +379,9 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { } } '"' => { - let def = parse_def(st, TypeWithId, conv); + let _ = parse_def(st, TypeWithId, conv); let inner = parse_ty(st, conv); - ty::mk_with_id(st.tcx, inner, def) + inner } 'B' => ty::mk_opaque_box(st.tcx), 'a' => { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 238f34b8c01b9..aa103609be0a6 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -77,19 +77,6 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) { Some(a) => { w.write_str(*a.s); return; } None => { let pos = w.tell(); - match ty::type_def_id(t) { - Some(def_id) => { - // Do not emit node ids that map to unexported names. Those - // are not helpful. - if def_id.crate != local_crate || - (cx.reachable)(def_id.node) { - w.write_char('"'); - w.write_str((cx.ds)(def_id)); - w.write_char('|'); - } - } - _ => {} - } enc_sty(w, cx, /*bad*/copy ty::get(t).sty); let end = w.tell(); let len = end - pos; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 7e64a219ecdd0..af8a873d8c88a 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -403,24 +403,24 @@ pub fn set_optimize_for_size(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, lib::llvm::OptimizeForSizeAttribute - as c_ulonglong, - 0u as c_ulonglong); + as c_uint, + 0); } } pub fn set_no_inline(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, - lib::llvm::NoInlineAttribute as c_ulonglong, - 0u as c_ulonglong); + lib::llvm::NoInlineAttribute as c_uint, + 0); } } pub fn set_no_unwind(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, - lib::llvm::NoUnwindAttribute as c_ulonglong, - 0u as c_ulonglong); + lib::llvm::NoUnwindAttribute as c_uint, + 0); } } @@ -429,15 +429,16 @@ pub fn set_no_unwind(f: ValueRef) { pub fn set_uwtable(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, - lib::llvm::UWTableAttribute as c_ulonglong, - 0u as c_ulonglong); + lib::llvm::UWTableAttribute as c_uint, + 0); } } pub fn set_inline_hint(f: ValueRef) { unsafe { - llvm::LLVMAddFunctionAttr(f, lib::llvm::InlineHintAttribute - as c_ulonglong, 0u as c_ulonglong); + llvm::LLVMAddFunctionAttr(f, + lib::llvm::InlineHintAttribute as c_uint, + 0); } } @@ -453,14 +454,15 @@ pub fn set_inline_hint_if_appr(attrs: &[ast::attribute], pub fn set_always_inline(f: ValueRef) { unsafe { - llvm::LLVMAddFunctionAttr(f, lib::llvm::AlwaysInlineAttribute - as c_ulonglong, 0u as c_ulonglong); + llvm::LLVMAddFunctionAttr(f, + lib::llvm::AlwaysInlineAttribute as c_uint, + 0); } } -pub fn set_custom_stack_growth_fn(f: ValueRef) { +pub fn set_fixed_stack_segment(f: ValueRef) { unsafe { - llvm::LLVMAddFunctionAttr(f, 0u as c_ulonglong, 1u as c_ulonglong); + llvm::LLVMAddFunctionAttr(f, 0, 1 << (39 - 32)); } } @@ -1782,6 +1784,7 @@ pub fn trans_closure(ccx: @CrateContext, param_substs: Option<@param_substs>, id: ast::node_id, impl_id: Option, + attributes: &[ast::attribute], maybe_load_env: &fn(fn_ctxt), finish: &fn(block)) { ccx.stats.n_closures += 1; @@ -1792,10 +1795,20 @@ pub fn trans_closure(ccx: @CrateContext, param_substs.repr(ccx.tcx)); // Set up arguments to the function. - let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs, - Some(body.span)); - let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, - decl.inputs); + let fcx = new_fn_ctxt_w_id(ccx, + path, + llfndecl, + id, + impl_id, + param_substs, + Some(body.span)); + let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, decl.inputs); + + // Set the fixed stack segment flag if necessary. + if attr::attrs_contains_name(attributes, "fixed_stack_segment") { + set_no_inline(fcx.llfn); + set_fixed_stack_segment(fcx.llfn); + } // Set GC for function. if ccx.sess.opts.gc { @@ -1848,7 +1861,8 @@ pub fn trans_fn(ccx: @CrateContext, ty_self: self_arg, param_substs: Option<@param_substs>, id: ast::node_id, - impl_id: Option) { + impl_id: Option, + attrs: &[ast::attribute]) { let do_time = ccx.sess.trans_stats(); let start = if do_time { time::get_time() } else { time::Timespec::new(0, 0) }; @@ -1858,8 +1872,16 @@ pub fn trans_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; let the_path_str = path_str(ccx.sess, path); - trans_closure(ccx, path, decl, body, llfndecl, ty_self, - param_substs, id, impl_id, + trans_closure(ccx, + path, + decl, + body, + llfndecl, + ty_self, + param_substs, + id, + impl_id, + attrs, |fcx| { if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); @@ -2031,8 +2053,16 @@ pub fn trans_struct_dtor(ccx: @CrateContext, } /* Translate the dtor body */ let decl = ast_util::dtor_dec(); - trans_fn(ccx, path, &decl, body, lldecl, - impl_self(class_ty), psubsts, dtor_id, None); + trans_fn(ccx, + path, + &decl, + body, + lldecl, + impl_self(class_ty), + psubsts, + dtor_id, + None, + []); lldecl } @@ -2081,7 +2111,14 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, vec::append(/*bad*/copy *path, ~[path_name(item.ident)]), - decl, body, llfndecl, no_self, None, item.id, None); + decl, + body, + llfndecl, + no_self, + None, + item.id, + None, + item.attrs); } else { for body.node.stmts.each |stmt| { match stmt.node { diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 0ef9d4af60487..252a10f8a8bbc 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -409,6 +409,15 @@ pub fn trans_expr_fn(bcx: block, ~"expr_fn"); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); + // Always mark inline if this is a loop body. This is important for + // performance on many programs with tight loops. + if is_loop_body.is_some() { + set_always_inline(llfn); + } else { + // Can't hurt. + set_inline_hint(llfn); + } + let Result {bcx: bcx, val: closure} = match sigil { ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => { let cap_vars = *ccx.maps.capture_map.get(&user_id); @@ -416,9 +425,16 @@ pub fn trans_expr_fn(bcx: block, None => None}; let ClosureResult {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, sigil, ret_handle); - trans_closure(ccx, sub_path, decl, - body, llfn, no_self, - /*bad*/ copy bcx.fcx.param_substs, user_id, None, + trans_closure(ccx, + sub_path, + decl, + body, + llfn, + no_self, + /*bad*/ copy bcx.fcx.param_substs, + user_id, + None, + [], |fcx| load_environment(fcx, cdata_ty, cap_vars, ret_handle.is_some(), sigil), |bcx| { diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 387caa4d8d31f..b1fb403f2a8bd 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -315,11 +315,11 @@ pub fn trans_foreign_mod(ccx: @CrateContext, { let llwrapfn = get_item_val(ccx, id); let tys = shim_types(ccx, id); - if attr::attrs_contains_name( - foreign_item.attrs, "rust_stack") - { + if attr::attrs_contains_name(foreign_item.attrs, "rust_stack") { build_direct_fn(ccx, llwrapfn, foreign_item, &tys, cc); + } else if attr::attrs_contains_name(foreign_item.attrs, "fast_ffi") { + build_fast_ffi_fn(ccx, llwrapfn, foreign_item, &tys, cc); } else { let llshimfn = build_shim_fn(ccx, foreign_item, &tys, cc); @@ -379,16 +379,47 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_direct_fn(ccx: @CrateContext, decl: ValueRef, item: @ast::foreign_item, tys: &ShimTypes, cc: lib::llvm::CallConv) { + debug!("build_direct_fn(%s)", *link_name(ccx, item)); + + let fcx = new_fn_ctxt(ccx, ~[], decl, None); + let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; + let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); + let ty = ty::lookup_item_type(ccx.tcx, + ast_util::local_def(item.id)).ty; + let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { + get_param(decl, i + first_real_arg) + }); + let retval = Call(bcx, llbasefn, args); + let ret_ty = ty::ty_fn_ret(ty); + if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { + Store(bcx, retval, fcx.llretptr); + } + build_return(bcx); + finish_fn(fcx, lltop); + } + + // FIXME (#2535): this is very shaky and probably gets ABIs wrong all + // over the place + fn build_fast_ffi_fn(ccx: @CrateContext, + decl: ValueRef, + item: @ast::foreign_item, + tys: &ShimTypes, + cc: lib::llvm::CallConv) { + debug!("build_fast_ffi_fn(%s)", *link_name(ccx, item)); + let fcx = new_fn_ctxt(ccx, ~[], decl, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); + set_no_inline(fcx.llfn); + set_fixed_stack_segment(fcx.llfn); let ty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(item.id)).ty; let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { get_param(decl, i + first_real_arg) }); let retval = Call(bcx, llbasefn, args); - if !ty::type_is_nil(ty::ty_fn_ret(ty)) { + let ret_ty = ty::ty_fn_ret(ty); + if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { Store(bcx, retval, fcx.llretptr); } build_return(bcx); @@ -1005,7 +1036,16 @@ pub fn trans_foreign_fn(ccx: @CrateContext, ))); let llty = type_of_fn_from_ty(ccx, t); let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty); - trans_fn(ccx, path, decl, body, llfndecl, no_self, None, id, None); + trans_fn(ccx, + path, + decl, + body, + llfndecl, + no_self, + None, + id, + None, + []); return llfndecl; } diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 15c2e8e3d9350..3f2fb95513a39 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -116,7 +116,8 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, self_kind, None, mth.id, - Some(impl_did)); + Some(impl_did), + []); } local_def(mth.id) } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index c518605faf13a..d3a15cbbfe150 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -137,7 +137,8 @@ pub fn trans_method(ccx: @CrateContext, self_arg, param_substs, method.id, - Some(impl_id)); + Some(impl_id), + []); } pub fn trans_self_arg(bcx: block, diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 97dc3fed780f0..be3e4ccae1508 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -195,7 +195,16 @@ pub fn monomorphic_fn(ccx: @CrateContext, }, _) => { let d = mk_lldecl(); set_inline_hint_if_appr(/*bad*/copy i.attrs, d); - trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None); + trans_fn(ccx, + pt, + decl, + body, + d, + no_self, + psubsts, + fn_id.node, + None, + []); d } ast_map::node_item(*) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 335c9824354d2..bed1226968dbd 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -134,7 +134,6 @@ impl to_bytes::IterBytes for creader_cache_key { struct intern_key { sty: *sty, - o_def_id: Option } // NB: Do not replace this with #[deriving(Eq)]. The automatically-derived @@ -143,7 +142,7 @@ struct intern_key { impl cmp::Eq for intern_key { fn eq(&self, other: &intern_key) -> bool { unsafe { - *self.sty == *other.sty && self.o_def_id == other.o_def_id + *self.sty == *other.sty } } fn ne(&self, other: &intern_key) -> bool { @@ -154,7 +153,7 @@ impl cmp::Eq for intern_key { impl to_bytes::IterBytes for intern_key { fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { unsafe { - to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f); + (*self.sty).iter_bytes(lsb0, f); } } } @@ -233,7 +232,7 @@ pub type ctxt = @ctxt_; struct ctxt_ { diag: @syntax::diagnostic::span_handler, - interner: @mut HashMap, + interner: @mut HashMap, next_id: @mut uint, vecs_implicitly_copyable: bool, legacy_modes: bool, @@ -304,7 +303,7 @@ struct ctxt_ { trait_impls: @mut HashMap> } -enum tbox_flag { +pub enum tbox_flag { has_params = 1, has_self = 2, needs_infer = 4, @@ -317,13 +316,12 @@ enum tbox_flag { needs_subst = 1 | 2 | 8 } -type t_box = @t_box_; +pub type t_box = &'static t_box_; -struct t_box_ { +pub struct t_box_ { sty: sty, id: uint, flags: uint, - o_def_id: Option } // To reduce refcounting cost, we're representing types as unsafe pointers @@ -356,7 +354,6 @@ pub fn type_needs_infer(t: t) -> bool { pub fn type_has_regions(t: t) -> bool { tbox_has_flag(get(t), has_regions) } -pub fn type_def_id(t: t) -> Option { get(t).o_def_id } pub fn type_id(t: t) -> uint { get(t).id } #[deriving(Eq)] @@ -493,6 +490,53 @@ pub struct substs { tps: ~[t] } +mod primitives { + use super::{sty, t_box_}; + + use syntax::ast; + + macro_rules! def_prim_ty( + ($name:ident, $sty:expr, $id:expr) => ( + pub static $name: t_box_ = t_box_ { + sty: $sty, + id: $id, + flags: 0, + }; + ) + ) + + def_prim_ty!(TY_NIL, super::ty_nil, 0) + def_prim_ty!(TY_BOOL, super::ty_bool, 1) + def_prim_ty!(TY_INT, super::ty_int(ast::ty_i), 2) + def_prim_ty!(TY_CHAR, super::ty_int(ast::ty_char), 3) + def_prim_ty!(TY_I8, super::ty_int(ast::ty_i8), 4) + def_prim_ty!(TY_I16, super::ty_int(ast::ty_i16), 5) + def_prim_ty!(TY_I32, super::ty_int(ast::ty_i32), 6) + def_prim_ty!(TY_I64, super::ty_int(ast::ty_i64), 7) + def_prim_ty!(TY_UINT, super::ty_uint(ast::ty_u), 8) + def_prim_ty!(TY_U8, super::ty_uint(ast::ty_u8), 9) + def_prim_ty!(TY_U16, super::ty_uint(ast::ty_u16), 10) + def_prim_ty!(TY_U32, super::ty_uint(ast::ty_u32), 11) + def_prim_ty!(TY_U64, super::ty_uint(ast::ty_u64), 12) + def_prim_ty!(TY_FLOAT, super::ty_float(ast::ty_f), 13) + def_prim_ty!(TY_F32, super::ty_float(ast::ty_f32), 14) + def_prim_ty!(TY_F64, super::ty_float(ast::ty_f64), 15) + + pub static TY_BOT: t_box_ = t_box_ { + sty: super::ty_bot, + id: 16, + flags: super::has_ty_bot as uint, + }; + + pub static TY_ERR: t_box_ = t_box_ { + sty: super::ty_err, + id: 17, + flags: super::has_ty_err as uint, + }; + + pub static LAST_PRIMITIVE_ID: uint = 18; +} + // NB: If you change this, you'll probably want to change the corresponding // AST structure in libsyntax/ast.rs as well. #[deriving(Eq)] @@ -832,7 +876,7 @@ pub fn mk_ctxt(s: session::Session, @ctxt_ { diag: s.diagnostic(), interner: @mut HashMap::new(), - next_id: @mut 0, + next_id: @mut primitives::LAST_PRIMITIVE_ID, vecs_implicitly_copyable: vecs_implicitly_copyable, legacy_modes: legacy_modes, cstore: s.cstore, @@ -873,16 +917,25 @@ pub fn mk_ctxt(s: session::Session, } } - // Type constructors -fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) } // Interns a type/name combination, stores the resulting box in cx.interner, // and returns the box as cast to an unsafe ptr (see comments for t above). -fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { - let key = intern_key { sty: to_unsafe_ptr(&st), o_def_id: o_def_id }; +fn mk_t(cx: ctxt, +st: sty) -> t { + // Check for primitive types. + match st { + ty_nil => return mk_nil(cx), + ty_err => return mk_err(cx), + ty_bool => return mk_bool(cx), + ty_int(i) => return mk_mach_int(cx, i), + ty_uint(u) => return mk_mach_uint(cx, u), + ty_float(f) => return mk_mach_float(cx, f), + _ => {} + }; + + let key = intern_key { sty: to_unsafe_ptr(&st) }; match cx.interner.find(&key) { - Some(&t) => unsafe { return cast::reinterpret_cast(&t); }, + Some(t) => unsafe { return cast::transmute(&t.sty); }, _ => () } @@ -952,66 +1005,116 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { } } - let t = @t_box_ { + let t = ~t_box_ { sty: st, id: *cx.next_id, flags: flags, - o_def_id: o_def_id }; + + let sty_ptr = to_unsafe_ptr(&t.sty); + let key = intern_key { - sty: to_unsafe_ptr(&t.sty), - o_def_id: o_def_id + sty: sty_ptr, }; cx.interner.insert(key, t); *cx.next_id += 1; - unsafe { cast::reinterpret_cast(&t) } + + unsafe { + cast::transmute::<*sty, t>(sty_ptr) + } +} + +#[inline(always)] +pub fn mk_prim_t(cx: ctxt, primitive: &'static t_box_) -> t { + unsafe { + cast::transmute::<&'static t_box_, t>(primitive) + } } -pub fn mk_nil(cx: ctxt) -> t { mk_t(cx, ty_nil) } +#[inline(always)] +pub fn mk_nil(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_NIL) } -pub fn mk_err(cx: ctxt) -> t { mk_t(cx, ty_err) } +#[inline(always)] +pub fn mk_err(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_ERR) } -pub fn mk_bot(cx: ctxt) -> t { mk_t(cx, ty_bot) } +#[inline(always)] +pub fn mk_bot(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOT) } -pub fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) } +#[inline(always)] +pub fn mk_bool(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOOL) } -pub fn mk_int(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i)) } +#[inline(always)] +pub fn mk_int(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_INT) } -pub fn mk_i8(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i8)) } +#[inline(always)] +pub fn mk_i8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I8) } -pub fn mk_i16(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i16)) } +#[inline(always)] +pub fn mk_i16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I16) } -pub fn mk_i32(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i32)) } +#[inline(always)] +pub fn mk_i32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I32) } -pub fn mk_i64(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i64)) } +#[inline(always)] +pub fn mk_i64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I64) } -pub fn mk_float(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f)) } +#[inline(always)] +pub fn mk_float(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_FLOAT) } -pub fn mk_uint(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u)) } +#[inline(always)] +pub fn mk_f32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F32) } -pub fn mk_u8(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u8)) } +#[inline(always)] +pub fn mk_f64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F64) } -pub fn mk_u16(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u16)) } +#[inline(always)] +pub fn mk_uint(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_UINT) } -pub fn mk_u32(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u32)) } +#[inline(always)] +pub fn mk_u8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U8) } -pub fn mk_u64(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u64)) } +#[inline(always)] +pub fn mk_u16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U16) } -pub fn mk_f32(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f32)) } +#[inline(always)] +pub fn mk_u32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U32) } -pub fn mk_f64(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f64)) } +#[inline(always)] +pub fn mk_u64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U64) } -pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { mk_t(cx, ty_int(tm)) } +pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { + match tm { + ast::ty_i => mk_int(cx), + ast::ty_char => mk_char(cx), + ast::ty_i8 => mk_i8(cx), + ast::ty_i16 => mk_i16(cx), + ast::ty_i32 => mk_i32(cx), + ast::ty_i64 => mk_i64(cx), + } +} -pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { mk_t(cx, ty_uint(tm)) } +pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { + match tm { + ast::ty_u => mk_uint(cx), + ast::ty_u8 => mk_u8(cx), + ast::ty_u16 => mk_u16(cx), + ast::ty_u32 => mk_u32(cx), + ast::ty_u64 => mk_u64(cx), + } +} pub fn mk_mach_float(cx: ctxt, tm: ast::float_ty) -> t { - mk_t(cx, ty_float(tm)) + match tm { + ast::ty_f => mk_float(cx), + ast::ty_f32 => mk_f32(cx), + ast::ty_f64 => mk_f64(cx), + } } -pub fn mk_char(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_char)) } +#[inline(always)] +pub fn mk_char(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_CHAR) } pub fn mk_estr(cx: ctxt, t: vstore) -> t { mk_t(cx, ty_estr(t)) @@ -1127,10 +1230,6 @@ pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t { pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) } -pub fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t { - mk_t_with_id(cx, /*bad*/copy get(base).sty, Some(def_id)) -} - // Converts s to its machine type equivalent pub fn mach_sty(cfg: @session::config, t: t) -> sty { match get(t).sty { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index a3296f6c20985..3586a6955b8b4 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1037,16 +1037,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) let region_parameterization = RegionParameterization::from_variance_and_generics(rp, generics); let tpt = { - let ty = { - let t0 = ccx.to_ty(&type_rscope(region_parameterization), t); - // Do not associate a def id with a named, parameterized type - // like "foo". This is because otherwise ty_to_str will - // print the name as merely "foo", as it has no way to - // reconstruct the value of X. - if generics.is_parameterized() { t0 } else { - ty::mk_with_id(tcx, t0, def_id) - } - }; + let ty = ccx.to_ty(&type_rscope(region_parameterization), t); ty_param_bounds_and_ty { generics: ty_generics(ccx, rp, generics, 0), ty: ty diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 4a3447700bc8f..7b479bc7578bd 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -59,10 +59,13 @@ pub mod reader { use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc}; use serialize; + use core::cast::transmute; use core::int; use core::io; use core::prelude::*; + use core::ptr::offset; use core::str; + use core::unstable::intrinsics::bswap32; use core::vec; // ebml reading @@ -78,7 +81,8 @@ pub mod reader { next: uint } - fn vuint_at(data: &[u8], start: uint) -> Res { + #[inline(never)] + fn vuint_at_slow(data: &[u8], start: uint) -> Res { let a = data[start]; if a & 0x80u8 != 0u8 { return Res {val: (a & 0x7fu8) as uint, next: start + 1u}; @@ -87,18 +91,63 @@ pub mod reader { return Res {val: ((a & 0x3fu8) as uint) << 8u | (data[start + 1u] as uint), next: start + 2u}; - } else if a & 0x20u8 != 0u8 { + } + if a & 0x20u8 != 0u8 { return Res {val: ((a & 0x1fu8) as uint) << 16u | (data[start + 1u] as uint) << 8u | (data[start + 2u] as uint), next: start + 3u}; - } else if a & 0x10u8 != 0u8 { + } + if a & 0x10u8 != 0u8 { return Res {val: ((a & 0x0fu8) as uint) << 24u | (data[start + 1u] as uint) << 16u | (data[start + 2u] as uint) << 8u | (data[start + 3u] as uint), next: start + 4u}; - } else { error!("vint too big"); fail!(); } + } + fail!(~"vint too big"); + } + + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "x86_64")] + pub fn vuint_at(data: &[u8], start: uint) -> Res { + if data.len() - start < 4 { + return vuint_at_slow(data, start); + } + + unsafe { + let (ptr, _): (*u8, uint) = transmute(data); + let ptr = offset(ptr, start); + let ptr: *i32 = transmute(ptr); + let val = bswap32(*ptr); + let val: u32 = transmute(val); + if (val & 0x80000000) != 0 { + Res { + val: ((val >> 24) & 0x7f) as uint, + next: start + 1 + } + } else if (val & 0x40000000) != 0 { + Res { + val: ((val >> 16) & 0x3fff) as uint, + next: start + 2 + } + } else if (val & 0x20000000) != 0 { + Res { + val: ((val >> 8) & 0x1fffff) as uint, + next: start + 3 + } + } else { + Res { + val: (val & 0x0fffffff) as uint, + next: start + 4 + } + } + } + } + + #[cfg(target_arch = "arm")] + pub fn vuint_at(data: &[u8], start: uint) -> Res { + vuint_at_slow(data, start) } pub fn Doc(data: @~[u8]) -> Doc { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 54b2ad8514781..001eb48d67ddb 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -18,9 +18,11 @@ use util::interner; use core::cast; use core::char; +use core::cmp::Equiv; use core::hashmap::HashSet; use core::str; use core::task; +use core::to_bytes; #[auto_encode] #[auto_decode] @@ -355,6 +357,19 @@ pub mod special_idents { pub static type_self: ident = ident { repr: 36 }; // `Self` } +pub struct StringRef<'self>(&'self str); + +impl<'self> Equiv<@~str> for StringRef<'self> { + #[inline(always)] + fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) } +} + +impl<'self> to_bytes::IterBytes for StringRef<'self> { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { + (**self).iter_bytes(lsb0, f); + } +} + pub struct ident_interner { priv interner: Interner<@~str>, } @@ -372,6 +387,13 @@ pub impl ident_interner { fn len(&self) -> uint { self.interner.len() } + fn find_equiv>(&self, val: &Q) + -> Option { + match self.interner.find_equiv(val) { + Some(v) => Some(ast::ident { repr: v }), + None => None, + } + } } /* Key for thread-local data for sneaking interner information to the diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 4108871d0089c..7d4788199e6ac 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -13,6 +13,7 @@ // type, and vice versa. use core::prelude::*; +use core::cmp::Equiv; use core::hashmap::HashMap; pub struct Interner { @@ -64,6 +65,14 @@ pub impl Interner { fn get(&self, idx: uint) -> T { self.vect[idx] } fn len(&self) -> uint { let vect = &*self.vect; vect.len() } + + fn find_equiv>(&self, val: &Q) + -> Option { + match self.map.find_equiv(val) { + Some(v) => Some(*v), + None => None, + } + } } #[test] diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp index 90393acdd59d6..dbcbd7b83cf23 100644 --- a/src/rt/rust_sched_loop.cpp +++ b/src/rt/rust_sched_loop.cpp @@ -29,6 +29,8 @@ rust_sched_loop::rust_sched_loop(rust_scheduler *sched, int id, bool killed) : should_exit(false), cached_c_stack(NULL), extra_c_stack(NULL), + cached_big_stack(NULL), + extra_big_stack(NULL), dead_task(NULL), killed(killed), pump_signal(NULL), @@ -263,6 +265,11 @@ rust_sched_loop::run_single_turn() { destroy_exchange_stack(kernel->region(), cached_c_stack); cached_c_stack = NULL; } + assert(!extra_big_stack); + if (cached_big_stack) { + destroy_exchange_stack(kernel->region(), cached_big_stack); + cached_big_stack = NULL; + } sched->release_task_thread(); return sched_loop_state_exit; @@ -392,6 +399,13 @@ rust_sched_loop::prepare_c_stack(rust_task *task) { cached_c_stack = create_exchange_stack(kernel->region(), C_STACK_SIZE); } + assert(!extra_big_stack); + if (!cached_big_stack) { + cached_big_stack = create_exchange_stack(kernel->region(), + C_STACK_SIZE + + (C_STACK_SIZE * 2)); + cached_big_stack->is_big = 1; + } } void @@ -400,6 +414,10 @@ rust_sched_loop::unprepare_c_stack() { destroy_exchange_stack(kernel->region(), extra_c_stack); extra_c_stack = NULL; } + if (extra_big_stack) { + destroy_exchange_stack(kernel->region(), extra_big_stack); + extra_big_stack = NULL; + } } // diff --git a/src/rt/rust_sched_loop.h b/src/rt/rust_sched_loop.h index 736c09ee920ca..a099c5e0c7495 100644 --- a/src/rt/rust_sched_loop.h +++ b/src/rt/rust_sched_loop.h @@ -67,6 +67,8 @@ struct rust_sched_loop stk_seg *cached_c_stack; stk_seg *extra_c_stack; + stk_seg *cached_big_stack; + stk_seg *extra_big_stack; rust_task_list running_tasks; rust_task_list blocked_tasks; @@ -147,6 +149,10 @@ struct rust_sched_loop stk_seg *borrow_c_stack(); void return_c_stack(stk_seg *stack); + // Called by tasks when they need a big stack + stk_seg *borrow_big_stack(); + void return_big_stack(stk_seg *stack); + int get_id() { return this->id; } }; @@ -202,6 +208,32 @@ rust_sched_loop::return_c_stack(stk_seg *stack) { } } +// NB: Runs on the Rust stack. Might return NULL! +inline stk_seg * +rust_sched_loop::borrow_big_stack() { + assert(cached_big_stack); + stk_seg *your_stack; + if (extra_big_stack) { + your_stack = extra_big_stack; + extra_big_stack = NULL; + } else { + your_stack = cached_big_stack; + cached_big_stack = NULL; + } + return your_stack; +} + +// NB: Runs on the Rust stack +inline void +rust_sched_loop::return_big_stack(stk_seg *stack) { + assert(!extra_big_stack); + assert(stack); + if (!cached_big_stack) + cached_big_stack = stack; + else + extra_big_stack = stack; +} + // this is needed to appease the circular dependency gods #include "rust_task.h" diff --git a/src/rt/rust_stack.cpp b/src/rt/rust_stack.cpp index 64ca256ff4611..f07690a955ea2 100644 --- a/src/rt/rust_stack.cpp +++ b/src/rt/rust_stack.cpp @@ -13,6 +13,8 @@ #include "vg/valgrind.h" #include "vg/memcheck.h" +#include + #ifdef _LP64 const uintptr_t canary_value = 0xABCDABCDABCDABCD; #else @@ -61,6 +63,7 @@ create_stack(memory_region *region, size_t sz) { stk_seg *stk = (stk_seg *)region->malloc(total_sz, "stack"); memset(stk, 0, sizeof(stk_seg)); stk->end = (uintptr_t) &stk->data[sz]; + stk->is_big = 0; add_stack_canary(stk); register_valgrind_stack(stk); return stk; @@ -78,6 +81,7 @@ create_exchange_stack(rust_exchange_alloc *exchange, size_t sz) { stk_seg *stk = (stk_seg *)exchange->malloc(total_sz); memset(stk, 0, sizeof(stk_seg)); stk->end = (uintptr_t) &stk->data[sz]; + stk->is_big = 0; add_stack_canary(stk); register_valgrind_stack(stk); return stk; diff --git a/src/rt/rust_stack.h b/src/rt/rust_stack.h index 51b884e47b1e7..3b34b91e309cf 100644 --- a/src/rt/rust_stack.h +++ b/src/rt/rust_stack.h @@ -22,9 +22,7 @@ struct stk_seg { stk_seg *next; uintptr_t end; unsigned int valgrind_id; -#ifndef _LP64 - uint32_t pad; -#endif + uint8_t is_big; rust_task *task; uintptr_t canary; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 63dc1c9833e21..6db138b418e51 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -53,7 +53,8 @@ rust_task::rust_task(rust_sched_loop *sched_loop, rust_task_state state, disallow_yield(0), c_stack(NULL), next_c_sp(0), - next_rust_sp(0) + next_rust_sp(0), + big_stack(NULL) { LOGPTR(sched_loop, "new task", (uintptr_t)this); DLOG(sched_loop, task, "sizeof(task) = %d (0x%x)", @@ -457,8 +458,9 @@ rust_task::get_next_stack_size(size_t min, size_t current, size_t requested) { "min: %" PRIdPTR " current: %" PRIdPTR " requested: %" PRIdPTR, min, current, requested); - // Allocate at least enough to accomodate the next frame - size_t sz = std::max(min, requested); + // Allocate at least enough to accomodate the next frame, plus a little + // slack to avoid thrashing + size_t sz = std::max(min, requested + (requested / 2)); // And double the stack size each allocation const size_t max = 1024 * 1024; @@ -555,13 +557,64 @@ rust_task::cleanup_after_turn() { // Delete any spare stack segments that were left // behind by calls to prev_stack assert(stk); + while (stk->next) { stk_seg *new_next = stk->next->next; - free_stack(stk->next); + + if (stk->next->is_big) { + assert (big_stack == stk->next); + sched_loop->return_big_stack(big_stack); + big_stack = NULL; + } else { + free_stack(stk->next); + } + stk->next = new_next; } } +// NB: Runs on the Rust stack. Returns true if we successfully allocated the big +// stack and false otherwise. +bool +rust_task::new_big_stack() { + // If we have a cached big stack segment, use it. + if (big_stack) { + // Check to see if we're already on the big stack. + stk_seg *ss = stk; + while (ss != NULL) { + if (ss == big_stack) + return false; + ss = ss->prev; + } + + // Unlink the big stack. + if (big_stack->next) + big_stack->next->prev = big_stack->prev; + if (big_stack->prev) + big_stack->prev->next = big_stack->next; + } else { + stk_seg *borrowed_big_stack = sched_loop->borrow_big_stack(); + if (!borrowed_big_stack) { + dump_stacks(); + abort(); + } else { + big_stack = borrowed_big_stack; + } + } + + big_stack->task = this; + big_stack->next = stk->next; + if (big_stack->next) + big_stack->next->prev = big_stack; + big_stack->prev = stk; + if (stk) + stk->next = big_stack; + + stk = big_stack; + + return true; +} + static bool sp_in_stk_seg(uintptr_t sp, stk_seg *stk) { // Not positive these bounds for sp are correct. I think that the first @@ -601,9 +654,16 @@ rust_task::delete_all_stacks() { assert(stk->next == NULL); while (stk != NULL) { stk_seg *prev = stk->prev; - free_stack(stk); + + if (stk->is_big) + sched_loop->return_big_stack(stk); + else + free_stack(stk); + stk = prev; } + + big_stack = NULL; } /* diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 00d20fefc0ee5..e8b3ef44ac09e 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -133,6 +133,9 @@ #define RZ_BSD_32 (1024*20) #define RZ_BSD_64 (1024*20) +// The threshold beyond which we switch to the C stack. +#define STACK_THRESHOLD (1024 * 1024) + #ifdef __linux__ #ifdef __i386__ #define RED_ZONE_SIZE RZ_LINUX_32 @@ -263,9 +266,13 @@ rust_task : public kernel_owned uintptr_t next_c_sp; uintptr_t next_rust_sp; + // The big stack. + stk_seg *big_stack; + // Called when the atomic refcount reaches zero void delete_this(); + bool new_big_stack(); void new_stack_fast(size_t requested_sz); void new_stack(size_t requested_sz); void free_stack(stk_seg *stk); @@ -284,6 +291,8 @@ rust_task : public kernel_owned char const *file, size_t line); + void dump_stacks(); + friend void task_start_wrapper(spawn_args *a); friend void cleanup_task(cleanup_args *a); friend void reset_stack_limit_on_c_stack(reset_args *a); @@ -568,6 +577,11 @@ rust_task::new_stack_fast(size_t requested_sz) { // The minimum stack size, in bytes, of a Rust stack, excluding red zone size_t min_sz = sched_loop->min_stack_size; + if (requested_sz > STACK_THRESHOLD) { + if (new_big_stack()) + return; + } + // Try to reuse an existing stack segment if (stk != NULL && stk->next != NULL) { size_t next_sz = user_stack_size(stk->next); diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 9f39e1433fc63..e524e6de859c8 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -191,6 +191,14 @@ rust_upcall_malloc(type_desc *td, uintptr_t size) { return upcall_malloc(td, size); } +extern "C" CDECL uintptr_t +rust_upcall_malloc_noswitch(type_desc *td, uintptr_t size) { + rust_task *task = rust_get_current_task(); + s_malloc_args args = {task, 0, td, size}; + upcall_s_malloc(&args); + return args.retval; +} + /********************************************************************** * Called whenever an object in the task-local heap is freed. */ @@ -231,6 +239,13 @@ rust_upcall_free(void* ptr) { upcall_free(ptr); } +extern "C" CDECL void +rust_upcall_free_noswitch(void* ptr) { + rust_task *task = rust_get_current_task(); + s_free_args args = {task,ptr}; + upcall_s_free(&args); +} + /**********************************************************************/ extern "C" _Unwind_Reason_Code diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 59fd8991622c6..c32bd7dd61d6f 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -66,7 +66,9 @@ upcall_del_stack upcall_reset_stack_limit rust_upcall_fail rust_upcall_free +rust_upcall_free_noswitch rust_upcall_malloc +rust_upcall_malloc_noswitch rust_uv_loop_new rust_uv_loop_delete rust_uv_walk diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 5d422b2d2edc3..141276e86f098 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -15,6 +15,8 @@ // //===----------------------------------------------------------------------=== +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Linker.h" #include "llvm/PassManager.h" #include "llvm/IR/InlineAsm.h" @@ -152,7 +154,9 @@ class RustMCJITMemoryManager : public JITMemoryManager { unsigned SectionID); virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, bool isReadOnly); + + virtual bool applyPermissions(std::string *Str); virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); @@ -218,12 +222,6 @@ class RustMCJITMemoryManager : public JITMemoryManager { virtual void deallocateExceptionTable(void *ET) { llvm_unreachable("Unimplemented call"); } - virtual uint8_t* allocateDataSection(uintptr_t, unsigned int, unsigned int, bool) { - llvm_unreachable("Unimplemented call"); - } - virtual bool applyPermissions(std::string*) { - llvm_unreachable("Unimplemented call"); - } }; bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) { @@ -240,8 +238,9 @@ bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) { } uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { + unsigned Alignment, + unsigned SectionID, + bool isReadOnly) { if (!Alignment) Alignment = 16; uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment); @@ -249,9 +248,14 @@ uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size, return Addr; } +bool RustMCJITMemoryManager::applyPermissions(std::string *Str) { + // Empty. + return true; +} + uint8_t *RustMCJITMemoryManager::allocateCodeSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { + unsigned Alignment, + unsigned SectionID) { if (!Alignment) Alignment = 16; unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1); @@ -451,6 +455,7 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, TargetOptions Options; Options.NoFramePointerElim = true; Options.EnableSegmentedStacks = EnableSegmentedStacks; + Options.FixedStackSegmentSize = 2 * 1024 * 1024; // XXX: This is too big. PassManager *PM = unwrap(PMR); @@ -484,13 +489,12 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, } extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { - SMDiagnostic d; Module *m = ParseAssemblyFile(Filename, d, getGlobalContext()); if (m) { return wrap(m); } else { - LLVMRustError = d.getMessage().data(); + LLVMRustError = d.getMessage().str().c_str(); return NULL; } } diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 8a8962fb9d637..b75aa3c909b96 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -88,6 +88,7 @@ fn vector>(map: &mut M, n_keys: uint, dist: &[uint]) { } } +#[fixed_stack_segment] fn main() { let args = os::args(); let n_keys = {