From 15e6e8cf3e6b06a79968c2c4d3eadad5729f74e1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 3 Apr 2014 10:45:36 -0700 Subject: [PATCH 01/15] rustc: Stop using LLVMGetSectionName The recent pull request to remove libc from libstd has hit a wall in compiling on windows, and I've been trying to investigate on the try bots as to why (it compiles locally just fine). To the best of my knowledge, the LLVM section iterator is behaving badly when iterating over the sections of the libc DLL. Upon investigating the LLVMGetSectionName function in LLVM, I discovered that this function doesn't always return a null-terminated string. It returns the data pointer of a StringRef instance (LLVM's equivalent of &str essentially), but it has no method of returning the length of the name of the section. This commit modifies the section iteration when loading libraries to invoke a custom LLVMRustGetSectionName which will correctly return both the length and the data pointer. I have not yet verified that this will fix landing liblibc, as it will require a snapshot before doing a full test. Regardless, this is a worrisome situation regarding the LLVM API, and should likely be fixed anyway. --- src/librustc/lib/llvm.rs | 5 +++-- src/librustc/metadata/loader.rs | 8 +++++--- src/rustllvm/RustWrapper.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index a733d2672e8..9cfe064ad98 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1438,8 +1438,6 @@ pub mod llvm { -> Bool; /** Moves the section iterator to point to the next section. */ pub fn LLVMMoveToNextSection(SI: SectionIteratorRef); - /** Returns the current section name. */ - pub fn LLVMGetSectionName(SI: SectionIteratorRef) -> *c_char; /** Returns the current section size. */ pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong; /** Returns the current section contents as a string buffer. */ @@ -1784,6 +1782,9 @@ pub mod llvm { pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef); pub fn LLVMVersionMinor() -> c_int; + + pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, + data: *mut *c_char) -> c_int; } } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 8a3d6567c77..4dd892fd703 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -29,9 +29,10 @@ use std::cast; use std::cmp; use std::io; use std::os::consts::{macos, freebsd, linux, android, win32}; +use std::ptr; use std::rc::Rc; -use std::str; use std::slice; +use std::str; use collections::{HashMap, HashSet}; use flate; @@ -439,8 +440,9 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result(SI); +} + +extern "C" int +LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) { + StringRef ret; + if (error_code ec = (*unwrap(SI))->getName(ret)) + report_fatal_error(ec.message()); + *ptr = ret.data(); + return ret.size(); +} From 0bd6f2ce0b650ebcb1d2b05dc501a9ed4907b6d2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 3 Apr 2014 10:49:57 -0700 Subject: [PATCH 02/15] rustllvm: Remove a no longer needed file The .def.in files haven't been necessary since the switch to static linking awhile back. --- src/rustllvm/rustllvm.def.in | 635 ----------------------------------- 1 file changed, 635 deletions(-) delete mode 100644 src/rustllvm/rustllvm.def.in diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in deleted file mode 100644 index 0b4a619c419..00000000000 --- a/src/rustllvm/rustllvm.def.in +++ /dev/null @@ -1,635 +0,0 @@ -LLVMRustCreateMemoryBufferWithContentsOfFile -LLVMRustWriteOutputFile -LLVMRustGetLastError -LLVMRustConstSmallInt -LLVMRustConstInt -LLVMRustPrintPassTimings -LLVMRustStartMultithreading -LLVMCreateObjectFile -LLVMDisposeObjectFile -LLVMDisposeExecutionEngine -LLVMGetSections -LLVMDisposeSectionIterator -LLVMIsSectionIteratorAtEnd -LLVMMoveToNextSection -LLVMGetSectionName -LLVMGetSectionSize -LLVMGetSectionContents -LLVMABIAlignmentOfType -LLVMABISizeOfType -LLVMAddAggressiveDCEPass -LLVMAddAlias -LLVMAddArgumentPromotionPass -LLVMAddAttribute -LLVMAddBasicAliasAnalysisPass -LLVMAddCFGSimplificationPass -LLVMAddCase -LLVMAddClause -LLVMAddConstantMergePass -LLVMAddConstantPropagationPass -LLVMAddCorrelatedValuePropagationPass -LLVMAddDeadArgEliminationPass -LLVMAddDeadStoreEliminationPass -LLVMAddDemoteMemoryToRegisterPass -LLVMAddDestination -LLVMAddEarlyCSEPass -LLVMAddFunction -LLVMAddFunctionAttr -LLVMAddFunctionAttrString -LLVMAddFunctionAttrsPass -LLVMAddFunctionInliningPass -LLVMAddGVNPass -LLVMAddGlobal -LLVMAddGlobalDCEPass -LLVMAddGlobalInAddressSpace -LLVMAddGlobalOptimizerPass -LLVMAddIPConstantPropagationPass -LLVMAddIPSCCPPass -LLVMAddIncoming -LLVMAddIndVarSimplifyPass -LLVMAddInstrAttribute -LLVMAddInstructionCombiningPass -LLVMAddInternalizePass -LLVMAddJumpThreadingPass -LLVMAddLICMPass -LLVMAddLoopDeletionPass -LLVMAddLoopIdiomPass -LLVMAddLoopRotatePass -LLVMAddLoopUnrollPass -LLVMAddLoopUnswitchPass -LLVMAddMemCpyOptPass -LLVMAddNamedMetadataOperand -LLVMAddPromoteMemoryToRegisterPass -LLVMAddPruneEHPass -LLVMAddReassociatePass -LLVMAddSCCPPass -LLVMAddScalarReplAggregatesPass -LLVMAddScalarReplAggregatesPassSSA -LLVMAddScalarReplAggregatesPassWithThreshold -LLVMAddSimplifyLibCallsPass -LLVMAddStripDeadPrototypesPass -LLVMAddStripSymbolsPass -LLVMAddTailCallEliminationPass -LLVMAddTargetData -LLVMAddTypeBasedAliasAnalysisPass -LLVMAddVerifierPass -LLVMAlignOf -LLVMAppendBasicBlock -LLVMAppendBasicBlockInContext -LLVMArrayType -LLVMBasicBlockAsValue -LLVMBlockAddress -LLVMBuildAShr -LLVMBuildAtomicLoad -LLVMBuildAtomicStore -LLVMBuildAtomicCmpXchg -LLVMBuildAtomicRMW -LLVMBuildAtomicFence -LLVMBuildAdd -LLVMBuildAggregateRet -LLVMBuildAlloca -LLVMBuildAnd -LLVMBuildArrayAlloca -LLVMBuildArrayMalloc -LLVMBuildBinOp -LLVMBuildBitCast -LLVMBuildBr -LLVMBuildCall -LLVMBuildCast -LLVMBuildCondBr -LLVMBuildExactSDiv -LLVMBuildExtractElement -LLVMBuildExtractValue -LLVMBuildFAdd -LLVMBuildFCmp -LLVMBuildFDiv -LLVMBuildFMul -LLVMBuildFNeg -LLVMBuildFPCast -LLVMBuildFPExt -LLVMBuildFPToSI -LLVMBuildFPToUI -LLVMBuildFPTrunc -LLVMBuildFRem -LLVMBuildFSub -LLVMBuildFree -LLVMBuildGEP -LLVMBuildGlobalString -LLVMBuildGlobalStringPtr -LLVMBuildICmp -LLVMBuildInBoundsGEP -LLVMBuildIndirectBr -LLVMBuildInsertElement -LLVMBuildInsertValue -LLVMBuildIntCast -LLVMBuildIntToPtr -LLVMBuildInvoke -LLVMBuildIsNotNull -LLVMBuildIsNull -LLVMBuildLandingPad -LLVMBuildLShr -LLVMBuildLoad -LLVMBuildMalloc -LLVMBuildMul -LLVMBuildNSWAdd -LLVMBuildNSWMul -LLVMBuildNSWNeg -LLVMBuildNSWSub -LLVMBuildNUWAdd -LLVMBuildNUWMul -LLVMBuildNUWNeg -LLVMBuildNUWSub -LLVMBuildNeg -LLVMBuildNot -LLVMBuildOr -LLVMBuildPhi -LLVMBuildPointerCast -LLVMBuildPtrDiff -LLVMBuildPtrToInt -LLVMBuildResume -LLVMBuildRet -LLVMBuildRetVoid -LLVMBuildSDiv -LLVMBuildSExt -LLVMBuildSExtOrBitCast -LLVMBuildSIToFP -LLVMBuildSRem -LLVMBuildSelect -LLVMBuildShl -LLVMBuildShuffleVector -LLVMBuildStore -LLVMBuildStructGEP -LLVMBuildSub -LLVMBuildSwitch -LLVMBuildTrunc -LLVMBuildTruncOrBitCast -LLVMBuildUDiv -LLVMBuildUIToFP -LLVMBuildURem -LLVMBuildUnreachable -LLVMBuildVAArg -LLVMBuildXor -LLVMBuildZExt -LLVMBuildZExtOrBitCast -LLVMByteOrder -LLVMCallFrameAlignmentOfType -LLVMClearInsertionPosition -LLVMConstAShr -LLVMConstAdd -LLVMConstAllOnes -LLVMConstAnd -LLVMConstArray -LLVMConstBitCast -LLVMConstExactSDiv -LLVMConstExtractElement -LLVMConstExtractValue -LLVMConstFAdd -LLVMConstFCmp -LLVMConstFDiv -LLVMConstFMul -LLVMConstFNeg -LLVMConstFPCast -LLVMConstFPExt -LLVMConstFPToSI -LLVMConstFPToUI -LLVMConstFPTrunc -LLVMConstFRem -LLVMConstFSub -LLVMConstGEP -LLVMConstICmp -LLVMConstInBoundsGEP -LLVMConstInlineAsm -LLVMConstInsertElement -LLVMConstInsertValue -LLVMConstInt -LLVMConstIntCast -LLVMConstIntGetSExtValue -LLVMConstIntGetZExtValue -LLVMConstIntOfArbitraryPrecision -LLVMConstIntOfString -LLVMConstIntOfStringAndSize -LLVMConstIntToPtr -LLVMConstLShr -LLVMConstMul -LLVMConstNSWAdd -LLVMConstNSWMul -LLVMConstNSWNeg -LLVMConstNSWSub -LLVMConstNUWAdd -LLVMConstNUWMul -LLVMConstNUWNeg -LLVMConstNUWSub -LLVMConstNeg -LLVMConstNot -LLVMConstNull -LLVMConstOr -LLVMConstPointerCast -LLVMConstPointerNull -LLVMConstPtrToInt -LLVMConstReal -LLVMConstRealOfString -LLVMConstRealOfStringAndSize -LLVMConstSDiv -LLVMConstSExt -LLVMConstSExtOrBitCast -LLVMConstSIToFP -LLVMConstSRem -LLVMConstSelect -LLVMConstShl -LLVMConstShuffleVector -LLVMConstString -LLVMConstStringInContext -LLVMConstStruct -LLVMConstStructInContext -LLVMConstSub -LLVMConstTrunc -LLVMConstTruncOrBitCast -LLVMConstUDiv -LLVMConstUIToFP -LLVMConstURem -LLVMConstVector -LLVMConstXor -LLVMConstZExt -LLVMConstZExtOrBitCast -LLVMContextCreate -LLVMContextDispose -LLVMCopyStringRepOfTargetData -LLVMCountBasicBlocks -LLVMCountIncoming -LLVMCountParamTypes -LLVMCountParams -LLVMCountStructElementTypes -LLVMCreateBuilder -LLVMCreateBuilderInContext -LLVMCreateFunctionPassManager -LLVMCreateFunctionPassManagerForModule -LLVMCreateMemoryBufferWithContentsOfFile -LLVMCreateMemoryBufferWithSTDIN -LLVMCreateModuleProviderForExistingModule -LLVMCreateObjectFile -LLVMCreatePassManager -LLVMCreateTargetData -LLVMDeleteBasicBlock -LLVMDeleteFunction -LLVMDeleteGlobal -LLVMDisposeBuilder -LLVMDisposeMemoryBuffer -LLVMDisposeMessage -LLVMDisposeModule -LLVMDisposeModuleProvider -LLVMDisposeObjectFile -LLVMDisposePassManager -LLVMDisposeSectionIterator -LLVMDisposeTargetData -LLVMDoubleType -LLVMDoubleTypeInContext -LLVMDumpModule -LLVMDumpValue -LLVMElementAtOffset -LLVMFP128Type -LLVMFP128TypeInContext -LLVMFinalizeFunctionPassManager -LLVMFloatType -LLVMFloatTypeInContext -LLVMFunctionType -LLVMGetAlignment -LLVMGetArrayLength -LLVMGetAttribute -LLVMGetBasicBlockParent -LLVMGetBasicBlocks -LLVMGetBitcodeModule -LLVMGetBitcodeModuleInContext -LLVMGetBitcodeModuleProvider -LLVMGetBitcodeModuleProviderInContext -LLVMGetConstOpcode -LLVMGetCurrentDebugLocation -LLVMGetDataLayout -LLVMGetElementType -LLVMGetEntryBasicBlock -LLVMGetFirstBasicBlock -LLVMGetFirstFunction -LLVMGetFirstGlobal -LLVMGetFirstInstruction -LLVMGetFirstParam -LLVMGetFirstUse -LLVMGetFunctionAttr -LLVMGetFunctionCallConv -LLVMGetGC -LLVMGetGlobalContext -LLVMGetGlobalParent -LLVMGetGlobalPassRegistry -LLVMGetIncomingBlock -LLVMGetIncomingValue -LLVMGetInitializer -LLVMGetInsertBlock -LLVMGetInstructionCallConv -LLVMGetInstructionParent -LLVMGetIntTypeWidth -LLVMGetIntrinsicID -LLVMGetLastBasicBlock -LLVMGetLastFunction -LLVMGetLastGlobal -LLVMGetLastInstruction -LLVMGetLastParam -LLVMGetLinkage -LLVMGetMDKindID -LLVMGetMDKindIDInContext -LLVMGetMetadata -LLVMGetModuleContext -LLVMGetNamedFunction -LLVMGetNamedGlobal -LLVMGetNextBasicBlock -LLVMGetNextFunction -LLVMGetNextGlobal -LLVMGetNextInstruction -LLVMGetNextParam -LLVMGetNextUse -LLVMGetNumOperands -LLVMGetOperand -LLVMGetOrInsertFunction -LLVMGetParam -LLVMGetParamParent -LLVMGetParamTypes -LLVMGetParams -LLVMGetPointerAddressSpace -LLVMGetPointerToGlobal -LLVMGetPreviousBasicBlock -LLVMGetPreviousFunction -LLVMGetPreviousGlobal -LLVMGetPreviousInstruction -LLVMGetPreviousParam -LLVMGetReturnType -LLVMGetSection -LLVMGetSectionContents -LLVMGetSectionName -LLVMGetSectionSize -LLVMGetSections -LLVMGetStructElementTypes -LLVMGetTarget -LLVMGetTypeContext -LLVMGetTypeKind -LLVMGetUndef -LLVMGetUsedValue -LLVMGetUser -LLVMGetValueName -LLVMGetVectorSize -LLVMGetVisibility -LLVMHasMetadata -LLVMInitializeCodeGen -LLVMInitializeFunctionPassManager -LLVMInitializeIPA -LLVMInitializeInstCombine -LLVMInitializeScalarOpts -LLVMInitializeTarget -LLVMInitializeTransformUtils -LLVMInitializeARMAsmParser -LLVMInitializeMipsAsmParser -LLVMInitializeX86AsmParser -LLVMInitializeARMAsmPrinter -LLVMInitializeMipsAsmPrinter -LLVMInitializeX86AsmPrinter -LLVMInitializeARMDisassembler -LLVMInitializeMipsDisassembler -LLVMInitializeX86Disassembler -LLVMInitializeARMTarget -LLVMInitializeMipsTarget -LLVMInitializeX86Target -LLVMInitializeARMTargetMC -LLVMInitializeMipsTargetMC -LLVMInitializeX86TargetMC -LLVMInitializeARMTargetInfo -LLVMInitializeMipsTargetInfo -LLVMInitializeX86TargetInfo -LLVMInsertBasicBlock -LLVMInsertBasicBlockInContext -LLVMInsertIntoBuilder -LLVMInsertIntoBuilderWithName -LLVMInstructionEraseFromParent -LLVMInt16Type -LLVMInt16TypeInContext -LLVMInt1Type -LLVMInt1TypeInContext -LLVMInt32Type -LLVMInt32TypeInContext -LLVMInt64Type -LLVMInt64TypeInContext -LLVMInt8Type -LLVMInt8TypeInContext -LLVMIntPtrType -LLVMIntType -LLVMIntTypeInContext -LLVMIsAAllocaInst -LLVMIsAArgument -LLVMIsABasicBlock -LLVMIsABinaryOperator -LLVMIsABitCastInst -LLVMIsABranchInst -LLVMIsACallInst -LLVMIsACastInst -LLVMIsACmpInst -LLVMIsAConstant -LLVMIsAConstantAggregateZero -LLVMIsAConstantArray -LLVMIsAConstantExpr -LLVMIsAConstantFP -LLVMIsAConstantInt -LLVMIsAConstantPointerNull -LLVMIsAConstantStruct -LLVMIsAConstantVector -LLVMIsADbgDeclareInst -LLVMIsADbgInfoIntrinsic -LLVMIsAExtractElementInst -LLVMIsAExtractValueInst -LLVMIsAFCmpInst -LLVMIsAFPExtInst -LLVMIsAFPToSIInst -LLVMIsAFPToUIInst -LLVMIsAFPTruncInst -LLVMIsAFunction -LLVMIsAGetElementPtrInst -LLVMIsAGlobalAlias -LLVMIsAGlobalValue -LLVMIsAGlobalVariable -LLVMIsAICmpInst -LLVMIsAInlineAsm -LLVMIsAInsertElementInst -LLVMIsAInsertValueInst -LLVMIsAInstruction -LLVMIsAIntToPtrInst -LLVMIsAIntrinsicInst -LLVMIsAInvokeInst -LLVMIsALoadInst -LLVMIsAMemCpyInst -LLVMIsAMemIntrinsic -LLVMIsAMemMoveInst -LLVMIsAMemSetInst -LLVMIsAPHINode -LLVMIsAPtrToIntInst -LLVMIsAReturnInst -LLVMIsASExtInst -LLVMIsASIToFPInst -LLVMIsASelectInst -LLVMIsAShuffleVectorInst -LLVMIsAStoreInst -LLVMIsASwitchInst -LLVMIsATerminatorInst -LLVMIsATruncInst -LLVMIsAUIToFPInst -LLVMIsAUnaryInstruction -LLVMIsAUndefValue -LLVMIsAUnreachableInst -LLVMIsAUser -LLVMIsAVAArgInst -LLVMIsAZExtInst -LLVMIsConstant -LLVMIsDeclaration -LLVMIsFunctionVarArg -LLVMIsGlobalConstant -LLVMIsNull -LLVMIsPackedStruct -LLVMIsSectionIteratorAtEnd -LLVMIsTailCall -LLVMIsThreadLocal -LLVMIsUndef -LLVMLabelType -LLVMLabelTypeInContext -LLVMLinkInInterpreter -LLVMMDNode -LLVMMDNodeInContext -LLVMMDString -LLVMMDStringInContext -LLVMMetadataTypeInContext -LLVMModuleCreateWithName -LLVMModuleCreateWithNameInContext -LLVMMoveBasicBlockAfter -LLVMMoveBasicBlockBefore -LLVMMoveToNextSection -LLVMOffsetOfElement -LLVMPPCFP128Type -LLVMPPCFP128TypeInContext -LLVMParseBitcode -LLVMParseBitcodeInContext -LLVMPassManagerBuilderCreate -LLVMPassManagerBuilderDispose -LLVMPassManagerBuilderPopulateModulePassManager -LLVMPassManagerBuilderSetDisableSimplifyLibCalls -LLVMPassManagerBuilderSetDisableUnitAtATime -LLVMPassManagerBuilderPopulateFunctionPassManager -LLVMPassManagerBuilderSetDisableUnrollLoops -LLVMPassManagerBuilderSetOptLevel -LLVMPassManagerBuilderSetSizeLevel -LLVMPassManagerBuilderUseInlinerWithThreshold -LLVMPointerSize -LLVMPointerType -LLVMPositionBuilder -LLVMPositionBuilderAtEnd -LLVMPositionBuilderBefore -LLVMPreferredAlignmentOfGlobal -LLVMPreferredAlignmentOfType -LLVMRemoveAttribute -LLVMRemoveFunctionAttr -LLVMRemoveInstrAttribute -LLVMReplaceAllUsesWith -LLVMRunFunctionPassManager -LLVMRunPassManager -LLVMSetAlignment -LLVMSetCleanup -LLVMSetCurrentDebugLocation -LLVMSetDataLayout -LLVMSetDebug -LLVMSetFunctionCallConv -LLVMSetGC -LLVMSetGlobalConstant -LLVMSetInitializer -LLVMSetInstDebugLocation -LLVMSetInstrParamAlignment -LLVMSetInstructionCallConv -LLVMSetLinkage -LLVMSetMetadata -LLVMSetModuleInlineAsm -LLVMSetOperand -LLVMSetParamAlignment -LLVMSetSection -LLVMSetTailCall -LLVMSetTarget -LLVMSetThreadLocal -LLVMSetValueName -LLVMSetVisibility -LLVMSizeOf -LLVMSizeOfTypeInBits -LLVMStoreSizeOfType -LLVMStructType -LLVMStructTypeInContext -LLVMTypeOf -LLVMValueAsBasicBlock -LLVMValueIsBasicBlock -LLVMVectorType -LLVMVerifyFunction -LLVMVerifyModule -LLVMViewFunctionCFG -LLVMViewFunctionCFGOnly -LLVMVoidType -LLVMVoidTypeInContext -LLVMWriteBitcodeToFD -LLVMWriteBitcodeToFile -LLVMWriteBitcodeToFileHandle -LLVMX86FP80Type -LLVMX86FP80TypeInContext -LLVMX86MMXType -LLVMX86MMXTypeInContext -LLVMConstNamedStruct -LLVMStructCreateNamed -LLVMStructSetBody -LLVMInlineAsm -LLVMInitializePasses -LLVMDIBuilderCreate -LLVMDIBuilderDispose -LLVMDIBuilderFinalize -LLVMDIBuilderCreateCompileUnit -LLVMDIBuilderCreateStaticVariable -LLVMDIBuilderCreateLocalVariable -LLVMDIBuilderCreateFunction -LLVMDIBuilderCreateFile -LLVMDIBuilderCreateLexicalBlock -LLVMDIBuilderCreateBasicType -LLVMDIBuilderCreatePointerType -LLVMDIBuilderCreateMemberType -LLVMDIBuilderCreateStructType -LLVMDIBuilderGetOrCreateSubrange -LLVMDIBuilderCreateArrayType -LLVMDIBuilderCreateVectorType -LLVMDIBuilderCreateSubroutineType -LLVMDIBuilderGetOrCreateArray -LLVMDIBuilderInsertDeclareAtEnd -LLVMDIBuilderInsertDeclareBefore -LLVMDIBuilderCreateEnumerator -LLVMDIBuilderCreateEnumerationType -LLVMDIBuilderCreateUnionType -LLVMDIBuilderCreateTemplateTypeParameter -LLVMDIBuilderCreateOpDeref -LLVMDIBuilderCreateOpPlus -LLVMDIBuilderCreateComplexVariable -LLVMDIBuilderCreateNameSpace -LLVMDICompositeTypeSetTypeArray -LLVMSetUnnamedAddr -LLVMRustAddPass -LLVMRustAddAnalysisPasses -LLVMRustAddLibraryInfo -LLVMRustCreateTargetMachine -LLVMRustRunFunctionPassManager -LLVMRustPrintModule -LLVMRustDisposeTargetMachine -LLVMRustAddBuilderLibraryInfo -LLVMRustSetLLVMOptions -LLVMRustPrintPasses -LLVMRustSetNormalizedTarget -LLVMRustAddAlwaysInlinePass -LLVMAddReturnAttribute -LLVMRemoveReturnAttribute -LLVMTypeToString -LLVMAddColdAttribute -LLVMCreateMemoryBufferWithMemoryRange -LLVMCreateMemoryBufferWithMemoryRangeCopy -LLVMPassManagerBuilderPopulateLTOPassManager -LLVMRustLinkInExternalBitcode -LLVMRustRunRestrictionPass From f5a4837df0885368352d118e1e71f4853bf55bf8 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 3 Apr 2014 22:28:45 +1100 Subject: [PATCH 03/15] std: override clone_from for Vec. A vector can reuse its allocation (and the allocations/resources of any contained values) when cloning into an already-instantiated vector, so we might as well do so. --- src/libstd/lib.rs | 1 + src/libstd/vec.rs | 56 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fb6c1b4c8a3..7971c332b27 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -232,4 +232,5 @@ mod std { pub use to_str; pub use ty; pub use unstable; + pub use vec; } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 69c3a85b2f1..e414ff25d43 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -310,11 +310,24 @@ impl Vec { impl Clone for Vec { fn clone(&self) -> Vec { - let mut vector = Vec::with_capacity(self.len()); - for element in self.iter() { - vector.push((*element).clone()) + self.iter().map(|x| x.clone()).collect() + } + + fn clone_from(&mut self, other: &Vec) { + // drop anything in self that will not be overwritten + if self.len() > other.len() { + self.truncate(other.len()) } - vector + + // reuse the contained values' allocations/resources. + for (place, thing) in self.mut_iter().zip(other.iter()) { + place.clone_from(thing) + } + + // self.len <= other.len due to the truncate above, so the + // slice here is always in-bounds. + let len = self.len(); + self.extend(other.slice_from(len).iter().map(|x| x.clone())); } } @@ -1475,4 +1488,39 @@ mod tests { assert!(values == Vec::from_slice([2u8, 3, 5, 6, 7])); } + + #[test] + fn test_clone() { + let v: Vec = vec!(); + let w = vec!(1, 2, 3); + + assert_eq!(v, v.clone()); + + let z = w.clone(); + assert_eq!(w, z); + // they should be disjoint in memory. + assert!(w.as_ptr() != z.as_ptr()) + } + + #[test] + fn test_clone_from() { + let mut v = vec!(); + let three = vec!(~1, ~2, ~3); + let two = vec!(~4, ~5); + // zero, long + v.clone_from(&three); + assert_eq!(v, three); + + // equal + v.clone_from(&three); + assert_eq!(v, three); + + // long, short + v.clone_from(&two); + assert_eq!(v, two); + + // short, long + v.clone_from(&three); + assert_eq!(v, three) + } } From 696a0051819c424db2d074a2cc57bacae4488053 Mon Sep 17 00:00:00 2001 From: Arcterus Date: Thu, 3 Apr 2014 00:28:40 -0700 Subject: [PATCH 04/15] serialize: add a few missing pubs to base64 --- src/libserialize/base64.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 6aad2f5abbf..13e4a010a5e 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -23,11 +23,11 @@ pub enum CharacterSet { /// Contains configuration parameters for `to_base64`. pub struct Config { /// Character set to use - char_set: CharacterSet, + pub char_set: CharacterSet, /// True to pad output with `=` characters - pad: bool, + pub pad: bool, /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping - line_length: Option + pub line_length: Option } /// Configuration for RFC 4648 standard base64 encoding From 74ae36ccf215d434697da3e00fa12656aa32d781 Mon Sep 17 00:00:00 2001 From: klutzy Date: Tue, 1 Apr 2014 16:10:56 +0900 Subject: [PATCH 05/15] compiletest: Fix bitrotted win32 routines --- src/compiletest/procsrv.rs | 22 ++++++++++++---------- src/compiletest/runtest.rs | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index e00b864f2e9..34918e39182 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -13,23 +13,25 @@ use std::str; use std::io::process::{ProcessExit, Process, ProcessConfig, ProcessOutput}; #[cfg(target_os = "win32")] -fn target_env(lib_path: &str, prog: &str) -> Vec<(~str,~str)> { - - let mut env = os::env(); +fn target_env(lib_path: &str, prog: &str) -> Vec<(~str, ~str)> { + let env = os::env(); // Make sure we include the aux directory in the path assert!(prog.ends_with(".exe")); let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ".libaux"; - env = env.map(|pair| { - let (k,v) = (*pair).clone(); - if k == ~"PATH" { (~"PATH", v + ";" + lib_path + ";" + aux_path) } - else { (k,v) } - }); + let mut new_env: Vec<_> = env.move_iter().map(|(k, v)| { + let new_v = if "PATH" == k { + format!("{};{};{}", v, lib_path, aux_path) + } else { + v + }; + (k, new_v) + }).collect(); if prog.ends_with("rustc.exe") { - env.push((~"RUST_THREADS", ~"1")); + new_env.push((~"RUST_THREADS", ~"1")); } - return env; + return new_env; } #[cfg(target_os = "linux")] diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index b07588a914d..e057909a06c 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -529,7 +529,7 @@ fn check_expected_errors(expected_errors: Vec , c } } ).collect(); - str::from_chars( c ) + str::from_chars(c.as_slice()) } #[cfg(target_os = "win32")] From 35ed58c1e61890c5325b5d1a29846a10fa23a5fd Mon Sep 17 00:00:00 2001 From: klutzy Date: Thu, 3 Apr 2014 12:18:58 +0900 Subject: [PATCH 06/15] test/debug-info: Add/remove ignore-win32 flags Fixes #10474 --- src/test/debug-info/basic-types-globals-metadata.rs | 5 ++++- src/test/debug-info/basic-types-globals.rs | 1 + src/test/debug-info/basic-types-mut-globals.rs | 1 + src/test/debug-info/c-style-enum.rs | 4 +++- src/test/debug-info/lexical-scope-in-for-loop.rs | 1 - src/test/debug-info/lexical-scope-in-if.rs | 1 - src/test/debug-info/lexical-scope-in-match.rs | 1 - src/test/debug-info/lexical-scopes-in-block-expression.rs | 2 +- src/test/debug-info/simple-struct.rs | 1 + src/test/debug-info/simple-tuple.rs | 1 + src/test/debug-info/var-captured-in-nested-closure.rs | 1 - src/test/debug-info/vec-slices.rs | 1 + src/test/debug-info/vec.rs | 1 + 13 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/test/debug-info/basic-types-globals-metadata.rs b/src/test/debug-info/basic-types-globals-metadata.rs index 943af3d0437..efc6fda26e0 100644 --- a/src/test/debug-info/basic-types-globals-metadata.rs +++ b/src/test/debug-info/basic-types-globals-metadata.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g @@ -44,7 +45,9 @@ // check:type = f64 // debugger:continue -#[allow(unused_variable)]; +#![allow(unused_variable)] +#![allow(dead_code)] + static B: bool = false; static I: int = -1; diff --git a/src/test/debug-info/basic-types-globals.rs b/src/test/debug-info/basic-types-globals.rs index 4847144c57f..860a383468d 100644 --- a/src/test/debug-info/basic-types-globals.rs +++ b/src/test/debug-info/basic-types-globals.rs @@ -14,6 +14,7 @@ // about UTF-32 character encoding and will print a rust char as only // its numerical value. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/basic-types-mut-globals.rs b/src/test/debug-info/basic-types-mut-globals.rs index 51391faed7a..54c2e786ac4 100644 --- a/src/test/debug-info/basic-types-mut-globals.rs +++ b/src/test/debug-info/basic-types-mut-globals.rs @@ -14,6 +14,7 @@ // about UTF-32 character encoding and will print a rust char as only // its numerical value. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/c-style-enum.rs b/src/test/debug-info/c-style-enum.rs index 7229480b273..b570110d8d0 100644 --- a/src/test/debug-info/c-style-enum.rs +++ b/src/test/debug-info/c-style-enum.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g @@ -70,7 +71,8 @@ // debugger:print 'c-style-enum::MANUAL_THREE' // check:$18 = OneMillion -#[allow(unused_variable)]; +#![allow(unused_variable)] +#![allow(dead_code)] enum AutoDiscriminant { One, diff --git a/src/test/debug-info/lexical-scope-in-for-loop.rs b/src/test/debug-info/lexical-scope-in-for-loop.rs index 5aa6caf612e..75f1d779d01 100644 --- a/src/test/debug-info/lexical-scope-in-for-loop.rs +++ b/src/test/debug-info/lexical-scope-in-for-loop.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-win32 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/lexical-scope-in-if.rs b/src/test/debug-info/lexical-scope-in-if.rs index 719c97a730f..712880d50f0 100644 --- a/src/test/debug-info/lexical-scope-in-if.rs +++ b/src/test/debug-info/lexical-scope-in-if.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-win32 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/lexical-scope-in-match.rs b/src/test/debug-info/lexical-scope-in-match.rs index bdb8416eec5..041c8b5c13f 100644 --- a/src/test/debug-info/lexical-scope-in-match.rs +++ b/src/test/debug-info/lexical-scope-in-match.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-win32 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/lexical-scopes-in-block-expression.rs b/src/test/debug-info/lexical-scopes-in-block-expression.rs index 2a3fbecad9d..6626d75dc0c 100644 --- a/src/test/debug-info/lexical-scopes-in-block-expression.rs +++ b/src/test/debug-info/lexical-scopes-in-block-expression.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-win32 +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/simple-struct.rs b/src/test/debug-info/simple-struct.rs index 5f9789ff620..2e1cdeccad2 100644 --- a/src/test/debug-info/simple-struct.rs +++ b/src/test/debug-info/simple-struct.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/simple-tuple.rs b/src/test/debug-info/simple-tuple.rs index 877b6285d13..16b0061f25e 100644 --- a/src/test/debug-info/simple-tuple.rs +++ b/src/test/debug-info/simple-tuple.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/var-captured-in-nested-closure.rs b/src/test/debug-info/var-captured-in-nested-closure.rs index 3e4610289ae..3bf26ae8053 100644 --- a/src/test/debug-info/var-captured-in-nested-closure.rs +++ b/src/test/debug-info/var-captured-in-nested-closure.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-win32: FIXME #10474 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/vec-slices.rs b/src/test/debug-info/vec-slices.rs index b60e5818411..0c7e2740cd7 100644 --- a/src/test/debug-info/vec-slices.rs +++ b/src/test/debug-info/vec-slices.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs index ad88606d485..635a42d443e 100644 --- a/src/test/debug-info/vec.rs +++ b/src/test/debug-info/vec.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-win32: FIXME #13256 // ignore-android: FIXME(#10381) // compile-flags:-g From b4f7b6d6729e3d255477833b05e0fd0b58c9ee34 Mon Sep 17 00:00:00 2001 From: klutzy Date: Thu, 3 Apr 2014 12:34:26 +0900 Subject: [PATCH 07/15] test/run-pass: Add/remove some ignore-win32 flags --- src/test/run-pass/backtrace.rs | 3 ++- src/test/run-pass/extern-fn-reachable.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 7252e319372..edf0e195cb3 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-win32 FIXME #13259 // ignore-fast this is executing itself -#[no_uv]; +#![no_uv] extern crate native; diff --git a/src/test/run-pass/extern-fn-reachable.rs b/src/test/run-pass/extern-fn-reachable.rs index d0526b75c96..d0f12ae7b10 100644 --- a/src/test/run-pass/extern-fn-reachable.rs +++ b/src/test/run-pass/extern-fn-reachable.rs @@ -9,6 +9,7 @@ // except according to those terms. // ignore-fast +// ignore-win32 dynamic_lib can read dllexported symbols only // ignore-linux apparently dlsym doesn't work on program symbols? // ignore-android apparently dlsym doesn't work on program symbols? // ignore-freebsd apparently dlsym doesn't work on program symbols? From 2ae292473e2b96ea8429dff5f2f3581bc026582c Mon Sep 17 00:00:00 2001 From: Benjamin Adamson Date: Wed, 2 Apr 2014 20:06:55 -0700 Subject: [PATCH 08/15] Removed managed boxes from libarena. --- src/libarena/lib.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 2099d3c01c4..4f8e5ee3a29 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -23,8 +23,6 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://static.rust-lang.org/doc/master")] #![allow(missing_doc)] -#![feature(managed_boxes)] - #![allow(visible_private_types)] // NOTE: remove after a stage0 snap extern crate collections; @@ -301,7 +299,7 @@ fn test_arena_destructors() { for i in range(0u, 10) { // Arena allocate something with drop glue to make sure it // doesn't leak. - arena.alloc(|| @i); + arena.alloc(|| Rc::new(i)); // Allocate something with funny size and alignment, to keep // things interesting. arena.alloc(|| [0u8, 1u8, 2u8]); @@ -316,13 +314,13 @@ fn test_arena_destructors_fail() { for i in range(0u, 10) { // Arena allocate something with drop glue to make sure it // doesn't leak. - arena.alloc(|| { @i }); + arena.alloc(|| { Rc::new(i) }); // Allocate something with funny size and alignment, to keep // things interesting. arena.alloc(|| { [0u8, 1u8, 2u8] }); } // Now, fail while allocating - arena.alloc::<@int>(|| { + arena.alloc::>(|| { // Now fail. fail!(); }); From c1e52c71cae901c25b2cea7b47c834501e09ecb6 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 2 Apr 2014 16:54:33 -0700 Subject: [PATCH 09/15] `extern crate` and `mod` are not easily confused Remove some statements that used to refer to similarities between `mod` and `extern mod`, before the latter was renamed to `extern crate`. --- src/doc/tutorial.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 62e0fabdc05..65b3def8daf 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -2600,8 +2600,6 @@ As you can see, your module hierarchy is now three modules deep: There is the cr function, and the module `farm`. The module `farm` also contains two functions and a third module `barn`, which contains a function `hay`. -(In case you already stumbled over `extern crate`: It isn't directly related to a bare `mod`, we'll get to it later. ) - ## Paths and visibility We've now defined a nice module hierarchy. But how do we access the items in it from our `main` function? @@ -3050,7 +3048,6 @@ fn main() { } ~~~ -Despite its name, `extern crate` is a distinct construct from regular `mod` declarations: A statement of the form `extern crate foo;` will cause `rustc` to search for the crate `foo`, and if it finds a matching binary it lets you use it from inside your crate. From 544516ac63605a689c904504439e484bd5897522 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 2 Apr 2014 16:56:23 -0700 Subject: [PATCH 10/15] Fix reference to "these two traits." There are actually three traits listed. --- src/doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 65b3def8daf..352595e8a7a 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -2107,7 +2107,7 @@ references, or types where the only contained references have the `'static` lifetime. (For more on named lifetimes and their uses, see the [references and lifetimes guide][lifetimes].) -> ***Note:*** These two traits were referred to as 'kinds' in earlier +> ***Note:*** These built-in traits were referred to as 'kinds' in earlier > iterations of the language, and often still are. Additionally, the `Drop` trait is used to define destructors. This From 1ac8b34ccd02965886d3ca0bd83115c7f7b73729 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 2 Apr 2014 17:02:18 -0700 Subject: [PATCH 11/15] Minor spelling/grammar/usage fixes. Note: "different to" is not exactly incorrect, but "different from" is more commonly accepted in both US and Commonwealth English, and also more consistent with other usage within this tutorial. --- src/doc/tutorial.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 352595e8a7a..9e0f3ce19f6 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -2841,11 +2841,11 @@ use farm::cow; The path you give to `use` is per default global, meaning relative to the crate root, no matter how deep the module hierarchy is, or whether the module body it's written in -is contained in its own file (remember: files are irrelevant). +is contained in its own file. (Remember: files are irrelevant.) -This is different to other languages, where you often only find a single import construct that combines the semantic +This is different from other languages, where you often only find a single import construct that combines the semantic of `mod foo;` and `use`-statements, and which tend to work relative to the source file or use an absolute file path -- Rubys `require` or C/C++'s `#include` come to mind. +- Ruby's `require` or C/C++'s `#include` come to mind. However, it's also possible to import things relative to the module of the `use`-statement: Adding a `super::` in front of the path will start in the parent module, @@ -3025,7 +3025,7 @@ The nested `barn` module is private, but the `pub use` allows users of the module `farm` to access a function from `barn` without needing to know that `barn` exists. -In other words, you can use them to decouple an public api from their internal implementation. +In other words, you can use it to decouple a public api from its internal implementation. ## Using libraries From 898669c4e203ae91e2048fb6c0f8591c867bccc6 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 2 Apr 2014 17:23:52 -0400 Subject: [PATCH 12/15] fix Option<~ZeroSizeType> 1778b6361627c5894bf75ffecf427573af02d390 provided the guarantee of no `exchange_free` calls for ~ZeroSizeType, so a sentinel can now be used without overhead. Closes #11998 --- src/librustc/middle/trans/expr.rs | 21 ++++++++++++------- src/libstd/rt/global_heap.rs | 13 ++++++++++-- .../run-pass/empty-allocation-non-null.rs | 19 +++++++++++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 src/test/run-pass/empty-allocation-non-null.rs diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index bd8c84e85e5..49a4a3ed25c 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -67,7 +67,7 @@ use middle::typeck::MethodCall; use util::common::indenter; use util::ppaux::Repr; use util::nodemap::NodeMap; -use middle::trans::machine::llsize_of; +use middle::trans::machine::{llsize_of, llsize_of_alloc}; use middle::trans::type_::Type; use std::slice; @@ -1200,12 +1200,19 @@ fn trans_boxed_expr<'a>(bcx: &'a Block<'a>, let size = llsize_of(bcx.ccx(), llty); let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty, heap_exchange, size); - let custom_cleanup_scope = fcx.push_custom_cleanup_scope(); - fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope), - val, heap_exchange); - let bcx = trans_into(bcx, contents, SaveIn(val)); - fcx.pop_custom_cleanup_scope(custom_cleanup_scope); - immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock() + // Unique boxes do not allocate for zero-size types. The standard library may assume + // that `free` is never called on the pointer returned for `~ZeroSizeType`. + if llsize_of_alloc(bcx.ccx(), llty) == 0 { + let bcx = trans_into(bcx, contents, SaveIn(val)); + immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock() + } else { + let custom_cleanup_scope = fcx.push_custom_cleanup_scope(); + fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope), + val, heap_exchange); + let bcx = trans_into(bcx, contents, SaveIn(val)); + fcx.pop_custom_cleanup_scope(custom_cleanup_scope); + immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock() + } } else { let base::MallocResult { bcx, smart_ptr: bx, body } = base::malloc_general(bcx, contents_ty, heap); diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 23b23cf8af0..3917857e1af 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -64,12 +64,21 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 { } } +// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size +// allocations can point to this `static`. It would be incorrect to use a null +// pointer, due to enums assuming types like unique pointers are never null. +static EMPTY: () = (); + /// The allocator for unique pointers without contained managed pointers. #[cfg(not(test))] #[lang="exchange_malloc"] #[inline] -pub unsafe fn exchange_malloc(size: uint) -> *u8 { - malloc_raw(size) as *u8 +pub unsafe fn exchange_malloc(size: uint) -> *mut u8 { + if size == 0 { + &EMPTY as *() as *mut u8 + } else { + malloc_raw(size) + } } // FIXME: #7496 diff --git a/src/test/run-pass/empty-allocation-non-null.rs b/src/test/run-pass/empty-allocation-non-null.rs new file mode 100644 index 00000000000..9695296ec15 --- /dev/null +++ b/src/test/run-pass/empty-allocation-non-null.rs @@ -0,0 +1,19 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main() { + assert!(Some(~()).is_some()); + + struct Foo; + assert!(Some(~Foo).is_some()); + + let xs: ~[()] = ~[]; + assert!(Some(xs).is_some()); +} From 1a1c47b91824bae040ddc2d799e14365b5415762 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 2 Apr 2014 23:50:20 +0200 Subject: [PATCH 13/15] Update emacs mode to support new `#![inner(attribute)]` syntax. --- src/etc/emacs/rust-mode.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index 3a99af3446c..5cee600c2c0 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -196,8 +196,8 @@ ;; Special types (,(regexp-opt rust-special-types 'words) . font-lock-type-face) - ;; Attributes like `#[bar(baz)]` - (,(rust-re-grab (concat "#\\[" rust-re-ident "[^]]*\\]")) + ;; Attributes like `#[bar(baz)]` or `#![bar(baz)]` + (,(rust-re-grab (concat "#\\!?[" rust-re-ident "[^]]*\\]")) 1 font-lock-preprocessor-face) ;; Syntax extension invocations like `foo!`, highlight including the ! From 57e0908af395af1c10e28600b785b5366a43660c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 2 Apr 2014 01:19:41 -0700 Subject: [PATCH 14/15] syntax: Remove AbiSet, use one Abi This change removes the AbiSet from the AST, converting all usage to have just one Abi value. The current scheme selects a relevant ABI given a list of ABIs based on the target architecture and how relevant each ABI is to that architecture. Instead of this mildly complicated scheme, only one ABI will be allowed in abi strings, and pseudo-abis will be created for special cases as necessary. For example the "system" abi exists for stdcall on win32 and C on win64. Closes #10049 --- src/librustc/front/config.rs | 2 +- src/librustc/metadata/creader.rs | 2 +- src/librustc/metadata/encoder.rs | 10 +- src/librustc/metadata/tydecode.rs | 19 +- src/librustc/metadata/tyencode.rs | 11 +- src/librustc/middle/lint.rs | 3 +- src/librustc/middle/trans/base.rs | 14 +- src/librustc/middle/trans/callee.rs | 12 +- src/librustc/middle/trans/foreign.rs | 34 +-- src/librustc/middle/trans/meth.rs | 3 +- src/librustc/middle/trans/monomorphize.rs | 5 +- src/librustc/middle/trans/type_of.rs | 3 +- src/librustc/middle/ty.rs | 12 +- src/librustc/middle/ty_fold.rs | 2 +- src/librustc/middle/typeck/astconv.rs | 14 +- src/librustc/middle/typeck/check/method.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 8 +- src/librustc/middle/typeck/collect.rs | 22 +- src/librustc/middle/typeck/infer/coercion.rs | 3 +- src/librustc/middle/typeck/infer/combine.rs | 8 +- src/librustc/middle/typeck/mod.rs | 4 +- src/librustc/util/ppaux.rs | 18 +- src/librustdoc/clean.rs | 2 +- src/librustdoc/visit_ast.rs | 4 +- src/libsyntax/abi.rs | 274 ++----------------- src/libsyntax/ast.rs | 8 +- src/libsyntax/ast_map.rs | 14 +- src/libsyntax/ext/build.rs | 4 +- src/libsyntax/fold.rs | 4 +- src/libsyntax/parse/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 85 +++--- src/libsyntax/print/pprust.rs | 53 ++-- src/libsyntax/visit.rs | 4 +- 33 files changed, 205 insertions(+), 460 deletions(-) diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index b4861d196e0..cfbe772a165 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -90,7 +90,7 @@ fn fold_foreign_mod(cx: &mut Context, nm: &ast::ForeignMod) -> ast::ForeignMod { filter_view_item(cx, a).map(|x| cx.fold_view_item(x)) }).collect(); ast::ForeignMod { - abis: nm.abis, + abi: nm.abi, view_items: filtered_view_items, items: filtered_items } diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 36febfc1a09..d9578502646 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -187,7 +187,7 @@ fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option { fn visit_item(e: &Env, i: &ast::Item) { match i.node { ast::ItemForeignMod(ref fm) => { - if fm.abis.is_rust() || fm.abis.is_intrinsic() { + if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic { return; } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 1da698beb38..ec6bb7de380 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -33,7 +33,7 @@ use std::hash::Hash; use std::io::MemWriter; use std::str; use collections::HashMap; -use syntax::abi::AbiSet; +use syntax::abi; use syntax::ast::*; use syntax::ast; use syntax::ast_map::{PathElem, PathElems}; @@ -1217,7 +1217,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, nitem: &ForeignItem, index: @RefCell> >, path: PathElems, - abi: AbiSet) { + abi: abi::Abi) { index.borrow_mut().push(entry { val: nitem.id as i64, pos: ebml_w.writer.tell().unwrap(), @@ -1231,7 +1231,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(ecx.tcx,local_def(nitem.id))); encode_name(ebml_w, nitem.ident.name); - if abi.is_intrinsic() { + if abi == abi::RustIntrinsic { (ecx.encode_inlined_item)(ecx, ebml_w, IIForeignRef(nitem)); } else { encode_symbol(ecx, ebml_w, nitem.id); @@ -1279,11 +1279,11 @@ fn my_visit_foreign_item(ni: &ForeignItem, let mut ebml_w = unsafe { ebml_w.unsafe_clone() }; - let abis = ecx.tcx.map.get_foreign_abis(ni.id); + let abi = ecx.tcx.map.get_foreign_abi(ni.id); ecx.tcx.map.with_path(ni.id, |path| { encode_info_for_foreign_item(ecx, &mut ebml_w, ni, index, - path, abis); + path, abi); }); } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 7ff36f13b75..409957b8625 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -20,7 +20,6 @@ use middle::ty; use std::str; use std::uint; -use syntax::abi::AbiSet; use syntax::abi; use syntax::ast; use syntax::ast::*; @@ -460,18 +459,12 @@ fn parse_purity(c: char) -> Purity { } } -fn parse_abi_set(st: &mut PState) -> AbiSet { +fn parse_abi_set(st: &mut PState) -> abi::Abi { assert_eq!(next(st), '['); - let mut abis = AbiSet::empty(); - while peek(st) != ']' { - scan(st, |c| c == ',', |bytes| { - let abi_str = str::from_utf8(bytes).unwrap().to_owned(); - let abi = abi::lookup(abi_str).expect(abi_str); - abis.add(abi); - }); - } - assert_eq!(next(st), ']'); - return abis; + scan(st, |c| c == ']', |bytes| { + let abi_str = str::from_utf8(bytes).unwrap().to_owned(); + abi::lookup(abi_str).expect(abi_str) + }) } fn parse_onceness(c: char) -> ast::Onceness { @@ -505,7 +498,7 @@ fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy { let sig = parse_sig(st, |x,y| conv(x,y)); ty::BareFnTy { purity: purity, - abis: abi, + abi: abi, sig: sig } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 7e8480e4311..4053db72a28 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -23,7 +23,7 @@ use std::fmt; use middle::ty::param_ty; use middle::ty; -use syntax::abi::AbiSet; +use syntax::abi::Abi; use syntax::ast; use syntax::ast::*; use syntax::diagnostic::SpanHandler; @@ -341,12 +341,9 @@ fn enc_purity(w: &mut MemWriter, p: Purity) { } } -fn enc_abi_set(w: &mut MemWriter, abis: AbiSet) { +fn enc_abi(w: &mut MemWriter, abi: Abi) { mywrite!(w, "["); - abis.each(|abi| { - mywrite!(w, "{},", abi.name()); - true - }); + mywrite!(w, "{}", abi.name()); mywrite!(w, "]") } @@ -359,7 +356,7 @@ fn enc_onceness(w: &mut MemWriter, o: Onceness) { pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::BareFnTy) { enc_purity(w, ft.purity); - enc_abi_set(w, ft.abis); + enc_abi(w, ft.abi); enc_fn_sig(w, cx, &ft.sig); } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 97f5cca1cab..da74d0c7729 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -59,6 +59,7 @@ use std::u32; use std::u64; use std::u8; use collections::SmallIntMap; +use syntax::abi; use syntax::ast_map; use syntax::ast_util::IdVisitingOperation; use syntax::attr::{AttrMetaMethods, AttributeMethods}; @@ -892,7 +893,7 @@ fn check_item_ctypes(cx: &Context, it: &ast::Item) { } match it.node { - ast::ItemForeignMod(ref nmod) if !nmod.abis.is_intrinsic() => { + ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => { for ni in nmod.items.iter() { match ni.node { ast::ForeignItemFn(decl, _) => check_foreign_fn(cx, decl), diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 133634a9e79..09bbb95fdd0 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -855,8 +855,8 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val let name = csearch::get_symbol(&ccx.sess().cstore, did); match ty::get(t).sty { ty::ty_bare_fn(ref fn_ty) => { - match fn_ty.abis.for_target(ccx.sess().targ_cfg.os, - ccx.sess().targ_cfg.arch) { + match fn_ty.abi.for_target(ccx.sess().targ_cfg.os, + ccx.sess().targ_cfg.arch) { Some(Rust) | Some(RustIntrinsic) => { get_extern_rust_fn(ccx, fn_ty.sig.inputs.as_slice(), @@ -865,7 +865,7 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val did) } Some(..) | None => { - let c = foreign::llvm_calling_convention(ccx, fn_ty.abis); + let c = foreign::llvm_calling_convention(ccx, fn_ty.abi); let cconv = c.unwrap_or(lib::llvm::CCallConv); let llty = type_of_fn_from_ty(ccx, t); get_extern_fn(&mut *ccx.externs.borrow_mut(), ccx.llmod, @@ -1601,7 +1601,7 @@ impl<'a> Visitor<()> for TransItemVisitor<'a> { pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { let _icx = push_ctxt("trans_item"); match item.node { - ast::ItemFn(decl, purity, _abis, ref generics, body) => { + ast::ItemFn(decl, purity, _abi, ref generics, body) => { if purity == ast::ExternFn { let llfndecl = get_item_val(ccx, item.id); foreign::trans_rust_fn_with_foreign_abi( @@ -1721,7 +1721,7 @@ fn register_fn(ccx: &CrateContext, -> ValueRef { let f = match ty::get(node_type).sty { ty::ty_bare_fn(ref f) => { - assert!(f.abis.is_rust() || f.abis.is_intrinsic()); + assert!(f.abi == Rust || f.abi == RustIntrinsic); f } _ => fail!("expected bare rust fn or an intrinsic") @@ -1997,8 +1997,8 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { match ni.node { ast::ForeignItemFn(..) => { - let abis = ccx.tcx.map.get_foreign_abis(id); - foreign::register_foreign_item_fn(ccx, abis, ni) + let abi = ccx.tcx.map.get_foreign_abi(id); + foreign::register_foreign_item_fn(ccx, abi, ni) } ast::ForeignItemStatic(..) => { foreign::register_static(ccx, ni) diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index dae4b2b471b..13fcaa486f1 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -50,7 +50,7 @@ use util::ppaux::Repr; use middle::trans::type_::Type; use syntax::ast; -use syntax::abi::AbiSet; +use synabi = syntax::abi; use syntax::ast_map; pub struct MethodData { @@ -363,7 +363,7 @@ pub fn trans_fn_ref_with_vtables( match map_node { ast_map::NodeForeignItem(_) => { - tcx.map.get_foreign_abis(def_id.node).is_intrinsic() + tcx.map.get_foreign_abi(def_id.node) == synabi::RustIntrinsic } _ => false } @@ -572,13 +572,11 @@ pub fn trans_call_inner<'a>( }; let (abi, ret_ty) = match ty::get(callee_ty).sty { - ty::ty_bare_fn(ref f) => (f.abis, f.sig.output), - ty::ty_closure(ref f) => (AbiSet::Rust(), f.sig.output), + ty::ty_bare_fn(ref f) => (f.abi, f.sig.output), + ty::ty_closure(ref f) => (synabi::Rust, f.sig.output), _ => fail!("expected bare rust fn or closure in trans_call_inner") }; - let is_rust_fn = - abi.is_rust() || - abi.is_intrinsic(); + let is_rust_fn = abi == synabi::Rust || abi == synabi::RustIntrinsic; // Generate a location to store the result. If the user does // not care about the result, just make a stack slot. diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 158589393ef..e70d7bf7568 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -27,7 +27,7 @@ use middle::ty::FnSig; use middle::ty; use std::cmp; use std::libc::c_uint; -use syntax::abi::{Cdecl, Aapcs, C, AbiSet, Win64}; +use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi}; use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, System}; use syntax::codemap::Span; use syntax::parse::token::{InternedString, special_idents}; @@ -73,10 +73,10 @@ struct LlvmSignature { // Calls to external functions pub fn llvm_calling_convention(ccx: &CrateContext, - abis: AbiSet) -> Option { + abi: Abi) -> Option { let os = ccx.sess().targ_cfg.os; let arch = ccx.sess().targ_cfg.arch; - abis.for_target(os, arch).map(|abi| { + abi.for_target(os, arch).map(|abi| { match abi { RustIntrinsic => { // Intrinsics are emitted by monomorphic fn @@ -180,27 +180,27 @@ pub fn register_static(ccx: &CrateContext, } } -pub fn register_foreign_item_fn(ccx: &CrateContext, abis: AbiSet, +pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, foreign_item: &ast::ForeignItem) -> ValueRef { /*! * Registers a foreign function found in a library. * Just adds a LLVM global. */ - debug!("register_foreign_item_fn(abis={}, \ + debug!("register_foreign_item_fn(abi={}, \ path={}, \ foreign_item.id={})", - abis.repr(ccx.tcx()), + abi.repr(ccx.tcx()), ccx.tcx.map.path_to_str(foreign_item.id), foreign_item.id); - let cc = match llvm_calling_convention(ccx, abis) { + let cc = match llvm_calling_convention(ccx, abi) { Some(cc) => cc, None => { ccx.sess().span_fatal(foreign_item.span, format!("ABI `{}` has no suitable calling convention \ for target architecture", - abis.user_string(ccx.tcx()))); + abi.user_string(ccx.tcx()))); } }; @@ -263,8 +263,8 @@ pub fn trans_native_call<'a>( ccx.tn.val_to_str(llfn), ccx.tn.val_to_str(llretptr)); - let (fn_abis, fn_sig) = match ty::get(callee_ty).sty { - ty::ty_bare_fn(ref fn_ty) => (fn_ty.abis, fn_ty.sig.clone()), + let (fn_abi, fn_sig) = match ty::get(callee_ty).sty { + ty::ty_bare_fn(ref fn_ty) => (fn_ty.abi, fn_ty.sig.clone()), _ => ccx.sess().bug("trans_native_call called on non-function type") }; let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys.as_slice()); @@ -354,14 +354,14 @@ pub fn trans_native_call<'a>( llargs_foreign.push(llarg_foreign); } - let cc = match llvm_calling_convention(ccx, fn_abis) { + let cc = match llvm_calling_convention(ccx, fn_abi) { Some(cc) => cc, None => { // FIXME(#8357) We really ought to report a span here ccx.sess().fatal( format!("ABI string `{}` has no suitable ABI \ for target architecture", - fn_abis.user_string(ccx.tcx()))); + fn_abi.user_string(ccx.tcx()))); } }; @@ -435,9 +435,9 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) { for &foreign_item in foreign_mod.items.iter() { match foreign_item.node { ast::ForeignItemFn(..) => { - let abis = foreign_mod.abis; - if !(abis.is_rust() || abis.is_intrinsic()) { - register_foreign_item_fn(ccx, abis, foreign_item); + match foreign_mod.abi { + Rust | RustIntrinsic => {} + abi => { register_foreign_item_fn(ccx, abi, foreign_item); } } } _ => {} @@ -486,7 +486,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext, let t = ty::node_id_to_type(ccx.tcx(), node_id); let (cconv, output) = match ty::get(t).sty { ty::ty_bare_fn(ref fn_ty) => { - let c = llvm_calling_convention(ccx, fn_ty.abis); + let c = llvm_calling_convention(ccx, fn_ty.abi); (c.unwrap_or(lib::llvm::CCallConv), fn_ty.sig.output) } _ => fail!("expected bare fn in register_rust_fn_with_foreign_abi") @@ -534,7 +534,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext, // normal Rust function. This will be the type of the wrappee fn. let f = match ty::get(t).sty { ty::ty_bare_fn(ref f) => { - assert!(!f.abis.is_rust() && !f.abis.is_intrinsic()); + assert!(f.abi != Rust && f.abi != RustIntrinsic); f } _ => { diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index a206d42e589..851f8207cb6 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -34,6 +34,7 @@ use util::common::indenter; use util::ppaux::Repr; use std::c_str::ToCStr; +use syntax::abi::Rust; use syntax::parse::token; use syntax::{ast, ast_map, visit}; @@ -393,7 +394,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>, debug!("(translating trait callee) loading method"); // Replace the self type (&Self or ~Self) with an opaque pointer. let llcallee_ty = match ty::get(callee_ty).sty { - ty::ty_bare_fn(ref f) if f.abis.is_rust() => { + ty::ty_bare_fn(ref f) if f.abi == Rust => { type_of_rust_fn(ccx, true, f.sig.inputs.slice_from(1), f.sig.output) } _ => { diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 179fda7cc46..6f2dbc182b0 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -23,6 +23,7 @@ use middle::ty; use middle::typeck; use util::ppaux::Repr; +use syntax::abi; use syntax::ast; use syntax::ast_map; use syntax::ast_util::local_def; @@ -99,7 +100,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, match map_node { ast_map::NodeForeignItem(_) => { - if !ccx.tcx.map.get_foreign_abis(fn_id.node).is_intrinsic() { + if ccx.tcx.map.get_foreign_abi(fn_id.node) != abi::RustIntrinsic { // Foreign externs don't have to be monomorphized. return (get_item_val(ccx, fn_id.node), true); } @@ -150,7 +151,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, let f = match ty::get(mono_ty).sty { ty::ty_bare_fn(ref f) => { - assert!(f.abis.is_rust() || f.abis.is_intrinsic()); + assert!(f.abi == abi::Rust || f.abi == abi::RustIntrinsic); f } _ => fail!("expected bare rust fn or an intrinsic") diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index a78520c8f6b..f45ef457204 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -19,6 +19,7 @@ use util::ppaux::Repr; use middle::trans::type_::Type; +use syntax::abi; use syntax::ast; use syntax::owned_slice::OwnedSlice; @@ -75,7 +76,7 @@ pub fn type_of_fn_from_ty(cx: &CrateContext, fty: ty::t) -> Type { type_of_rust_fn(cx, true, f.sig.inputs.as_slice(), f.sig.output) } ty::ty_bare_fn(ref f) => { - if f.abis.is_rust() || f.abis.is_intrinsic() { + if f.abi == abi::Rust || f.abi == abi::RustIntrinsic { type_of_rust_fn(cx, false, f.sig.inputs.as_slice(), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index f9296926c74..85d47424e2b 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -51,7 +51,7 @@ use syntax::parse::token; use syntax::parse::token::InternedString; use syntax::{ast, ast_map}; use syntax::owned_slice::OwnedSlice; -use syntax::abi::AbiSet; +use syntax::abi; use syntax; use collections::enum_set::{EnumSet, CLike}; @@ -416,8 +416,8 @@ pub fn type_id(t: t) -> uint { get(t).id } #[deriving(Clone, Eq, TotalEq, Hash)] pub struct BareFnTy { pub purity: ast::Purity, - pub abis: AbiSet, - pub sig: FnSig + pub abi: abi::Abi, + pub sig: FnSig, } #[deriving(Clone, Eq, TotalEq, Hash)] @@ -796,7 +796,7 @@ pub enum type_err { terr_mismatch, terr_purity_mismatch(expected_found), terr_onceness_mismatch(expected_found), - terr_abi_mismatch(expected_found), + terr_abi_mismatch(expected_found), terr_mutability, terr_sigil_mismatch(expected_found), terr_box_mutability, @@ -1409,7 +1409,7 @@ pub fn mk_ctor_fn(cx: &ctxt, mk_bare_fn(cx, BareFnTy { purity: ast::ImpureFn, - abis: AbiSet::Rust(), + abi: abi::Rust, sig: FnSig { binder_id: binder_id, inputs: input_args, @@ -4677,7 +4677,7 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { ty_bare_fn(ref b) => { byte!(14); hash!(b.purity); - hash!(b.abis); + hash!(b.abi); } ty_closure(ref c) => { byte!(15); diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 7eae2ce3d33..02c4ffe68c1 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -48,7 +48,7 @@ pub trait TypeFolder { fty: &ty::BareFnTy) -> ty::BareFnTy { ty::BareFnTy { sig: self.fold_sig(&fty.sig), - abis: fty.abis, + abi: fty.abi, purity: fty.purity } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 5d2d221a774..82be7836168 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -60,7 +60,7 @@ use middle::typeck::rscope::{RegionScope}; use middle::typeck::lookup_def_tcx; use util::ppaux::Repr; -use syntax::abi::AbiSet; +use syntax::abi; use syntax::{ast, ast_util}; use syntax::codemap::Span; use syntax::owned_slice::OwnedSlice; @@ -519,12 +519,12 @@ pub fn ast_ty_to_ty( ty::mk_tup(tcx, flds) } ast::TyBareFn(ref bf) => { - if bf.decl.variadic && !bf.abis.is_c() { + if bf.decl.variadic && bf.abi != abi::C { tcx.sess.span_err(ast_ty.span, "variadic function must have C calling convention"); } ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.purity, - bf.abis, bf.decl)) + bf.abi, bf.decl)) } ast::TyClosure(ref f) => { if f.sigil == ast::ManagedSigil { @@ -666,20 +666,20 @@ pub fn ty_of_method( untransformed_self_ty: ty::t, explicit_self: ast::ExplicitSelf, decl: &ast::FnDecl) -> ty::BareFnTy { - ty_of_method_or_bare_fn(this, id, purity, AbiSet::Rust(), Some(SelfInfo { + ty_of_method_or_bare_fn(this, id, purity, abi::Rust, Some(SelfInfo { untransformed_self_ty: untransformed_self_ty, explicit_self: explicit_self }), decl) } pub fn ty_of_bare_fn(this: &AC, id: ast::NodeId, - purity: ast::Purity, abi: AbiSet, + purity: ast::Purity, abi: abi::Abi, decl: &ast::FnDecl) -> ty::BareFnTy { ty_of_method_or_bare_fn(this, id, purity, abi, None, decl) } fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, - purity: ast::Purity, abi: AbiSet, + purity: ast::Purity, abi: abi::Abi, opt_self_info: Option, decl: &ast::FnDecl) -> ty::BareFnTy { debug!("ty_of_method_or_bare_fn"); @@ -726,7 +726,7 @@ fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, return ty::BareFnTy { purity: purity, - abis: abi, + abi: abi, sig: ty::FnSig { binder_id: id, inputs: self_and_input_tys, diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 07ebcf7ee94..dce4e7fb06b 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1164,7 +1164,7 @@ impl<'a> LookupContext<'a> { let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { sig: fn_sig, purity: bare_fn_ty.purity, - abis: bare_fn_ty.abis.clone(), + abi: bare_fn_ty.abi.clone(), }); debug!("after replacing bound regions, fty={}", self.ty_to_str(fty)); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 5752a928358..20ab2b699c2 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -120,7 +120,7 @@ use std::mem::replace; use std::result; use std::slice; use std::vec::Vec; -use syntax::abi::AbiSet; +use syntax::abi; use syntax::ast::{Provided, Required}; use syntax::ast; use syntax::ast_util::local_def; @@ -599,7 +599,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { check_bounds_are_used(ccx, t.span, &generics.ty_params, tpt_ty); } ast::ItemForeignMod(ref m) => { - if m.abis.is_intrinsic() { + if m.abi == abi::RustIntrinsic { for item in m.items.iter() { check_intrinsic_type(ccx, *item); } @@ -612,7 +612,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { match item.node { ast::ForeignItemFn(ref fn_decl, _) => { - if fn_decl.variadic && !m.abis.is_c() { + if fn_decl.variadic && m.abi != abi::C { ccx.tcx.sess.span_err( item.span, "variadic function must have C calling convention"); } @@ -4224,7 +4224,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { }; let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { purity: ast::UnsafeFn, - abis: AbiSet::Intrinsic(), + abi: abi::RustIntrinsic, sig: FnSig {binder_id: it.id, inputs: inputs, output: output, diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index ca770615395..274f88ad4c3 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -48,7 +48,7 @@ use util::ppaux::Repr; use std::rc::Rc; use collections::HashSet; -use syntax::abi::AbiSet; +use syntax::abi; use syntax::ast::{RegionTyParamBound, TraitTyParamBound}; use syntax::ast; use syntax::ast_map; @@ -116,8 +116,8 @@ impl<'a> AstConv for CrateCtxt<'a> { match self.tcx.map.find(id.node) { Some(ast_map::NodeItem(item)) => ty_of_item(self, item), Some(ast_map::NodeForeignItem(foreign_item)) => { - let abis = self.tcx.map.get_foreign_abis(id.node); - ty_of_foreign_item(self, foreign_item, abis) + let abi = self.tcx.map.get_foreign_abi(id.node); + ty_of_foreign_item(self, foreign_item, abi) } x => { self.tcx.sess.bug(format!("unexpected sort of node \ @@ -550,10 +550,10 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, fn ensure_generics_abi(ccx: &CrateCtxt, span: Span, - abis: AbiSet, + abi: abi::Abi, generics: &ast::Generics) { if generics.ty_params.len() > 0 && - !(abis.is_rust() || abis.is_intrinsic()) { + !(abi == abi::Rust || abi == abi::RustIntrinsic) { ccx.tcx.sess.span_err(span, "foreign functions may not use type parameters"); } @@ -717,9 +717,9 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) { // map, and I regard each time that I use it as a personal and // moral failing, but at the moment it seems like the only // convenient way to extract the ABI. - ndm - let abis = ccx.tcx.map.get_foreign_abis(i.id); + let abi = ccx.tcx.map.get_foreign_abi(i.id); - let tpt = ty_of_foreign_item(ccx, i, abis); + let tpt = ty_of_foreign_item(ccx, i, abi); write_ty_to_tcx(ccx.tcx, i.id, tpt.ty); ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), tpt); @@ -891,7 +891,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item) pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: &ast::ForeignItem, - abis: AbiSet) -> ty::ty_param_bounds_and_ty + abi: abi::Abi) -> ty::ty_param_bounds_and_ty { match it.node { ast::ForeignItemFn(fn_decl, ref generics) => { @@ -899,7 +899,7 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, fn_decl, local_def(it.id), generics, - abis) + abi) } ast::ForeignItemStatic(t, _) => { ty::ty_param_bounds_and_ty { @@ -1003,7 +1003,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, decl: &ast::FnDecl, def_id: ast::DefId, ast_generics: &ast::Generics, - abis: AbiSet) + abi: abi::Abi) -> ty::ty_param_bounds_and_ty { for i in decl.inputs.iter() { @@ -1028,7 +1028,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, let t_fn = ty::mk_bare_fn( ccx.tcx, ty::BareFnTy { - abis: abis, + abi: abi, purity: ast::UnsafeFn, sig: ty::FnSig {binder_id: def_id.node, inputs: input_tys, diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 5dc55ab4b5c..dac018fb848 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -77,6 +77,7 @@ use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::resolve::try_resolve_tvar_shallow; use util::common::indenter; +use syntax::abi; use syntax::ast::MutImmutable; use syntax::ast; @@ -384,7 +385,7 @@ impl<'f> Coerce<'f> { debug!("coerce_from_bare_fn(a={}, b={})", a.inf_str(self.get_ref().infcx), b.inf_str(self.get_ref().infcx)); - if !fn_ty_a.abis.is_rust() || fn_ty_a.purity != ast::ImpureFn { + if fn_ty_a.abi != abi::Rust || fn_ty_a.purity != ast::ImpureFn { return self.subtype(a, b); } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 4a03e32dee8..749c1ee6938 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -67,7 +67,7 @@ use std::result; use syntax::ast::{Onceness, Purity}; use syntax::ast; use syntax::owned_slice::OwnedSlice; -use syntax::abi::AbiSet; +use syntax::abi; pub trait Combine { fn infcx<'a>(&'a self) -> &'a InferCtxt<'a>; @@ -195,10 +195,10 @@ pub trait Combine { fn bare_fn_tys(&self, a: &ty::BareFnTy, b: &ty::BareFnTy) -> cres { let purity = if_ok!(self.purities(a.purity, b.purity)); - let abi = if_ok!(self.abis(a.abis, b.abis)); + let abi = if_ok!(self.abi(a.abi, b.abi)); let sig = if_ok!(self.fn_sigs(&a.sig, &b.sig)); Ok(ty::BareFnTy {purity: purity, - abis: abi, + abi: abi, sig: sig}) } @@ -248,7 +248,7 @@ pub trait Combine { fn purities(&self, a: Purity, b: Purity) -> cres; - fn abis(&self, a: AbiSet, b: AbiSet) -> cres { + fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres { if a == b { Ok(a) } else { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index fb82bf9968a..d635a9bdec4 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -358,7 +358,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, } let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { purity: ast::ImpureFn, - abis: abi::AbiSet::Rust(), + abi: abi::Rust, sig: ty::FnSig { binder_id: main_id, inputs: Vec::new(), @@ -404,7 +404,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { purity: ast::ImpureFn, - abis: abi::AbiSet::Rust(), + abi: abi::Rust, sig: ty::FnSig { binder_id: start_id, inputs: vec!( diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 0f7de94a92d..4a1be783d9d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -23,7 +23,7 @@ use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_unboxed_vec, ty_infer}; use middle::ty; use middle::typeck; -use syntax::abi::AbiSet; +use syntax::abi; use syntax::ast_map; use syntax::codemap::{Span, Pos}; use syntax::parse::token; @@ -253,14 +253,14 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> ~str { } fn bare_fn_to_str(cx: &ctxt, purity: ast::Purity, - abis: AbiSet, + abi: abi::Abi, ident: Option, sig: &ty::FnSig) -> ~str { - let mut s = if abis.is_rust() { + let mut s = if abi == abi::Rust { ~"" } else { - format!("extern {} ", abis.to_str()) + format!("extern {} ", abi.to_str()) }; match purity { @@ -406,7 +406,7 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> ~str { closure_to_str(cx, *f) } ty_bare_fn(ref f) => { - bare_fn_to_str(cx, f.purity, f.abis, None, &f.sig) + bare_fn_to_str(cx, f.purity, f.abi, None, &f.sig) } ty_infer(infer_ty) => infer_ty.to_str(), ty_err => ~"[type error]", @@ -813,9 +813,9 @@ impl Repr for ast::Visibility { impl Repr for ty::BareFnTy { fn repr(&self, tcx: &ctxt) -> ~str { - format!("BareFnTy \\{purity: {:?}, abis: {}, sig: {}\\}", + format!("BareFnTy \\{purity: {:?}, abi: {}, sig: {}\\}", self.purity, - self.abis.to_str(), + self.abi.to_str(), self.sig.repr(tcx)) } } @@ -968,13 +968,13 @@ impl UserString for ast::Ident { } } -impl Repr for AbiSet { +impl Repr for abi::Abi { fn repr(&self, _tcx: &ctxt) -> ~str { self.to_str() } } -impl UserString for AbiSet { +impl UserString for abi::Abi { fn user_string(&self, _tcx: &ctxt) -> ~str { self.to_str() } diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index ff7f7c6e6f4..e92aec8e25c 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -975,7 +975,7 @@ impl Clean for ast::BareFnTy { type_params: Vec::new(), }, decl: self.decl.clean(), - abi: self.abis.to_str(), + abi: self.abi.to_str(), } } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 78c6940244c..a6c1ece6400 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -11,7 +11,7 @@ //! Rust AST Visitor. Extracts useful information and massages it into a form //! usable for clean -use syntax::abi::AbiSet; +use syntax::abi; use syntax::ast; use syntax::ast_util; use syntax::ast_map; @@ -95,7 +95,7 @@ impl<'a> RustdocVisitor<'a> { } pub fn visit_fn(&mut self, item: &ast::Item, fd: &ast::FnDecl, - purity: &ast::Purity, _abi: &AbiSet, + purity: &ast::Purity, _abi: &abi::Abi, gen: &ast::Generics) -> Function { debug!("Visiting fn"); Function { diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index caded1dc0b8..a40899de931 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -9,12 +9,11 @@ // except according to those terms. use std::fmt; -use std::fmt::Show; #[deriving(Eq)] pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, } -#[deriving(Eq, TotalEq, Hash)] +#[deriving(Eq, TotalEq, Hash, Encodable, Decodable, Clone)] pub enum Abi { // NB: This ordering MUST match the AbiDatas array below. // (This is ensured by the test indices_are_correct().) @@ -65,11 +64,6 @@ pub enum AbiArchitecture { Archs(u32) // Multiple architectures (bitset) } -#[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] -pub struct AbiSet { - bits: u32 // each bit represents one of the abis below -} - static AbiDatas: &'static [AbiData] = &[ // Platform-specific ABIs AbiData {abi: Cdecl, name: "cdecl", abi_arch: Archs(IntelBits)}, @@ -136,12 +130,20 @@ impl Abi { self.data().name } - pub fn for_target(&self, os: Os, arch: Architecture) -> Abi { - match (*self, os, arch) { + pub fn for_target(&self, os: Os, arch: Architecture) -> Option { + // If this ABI isn't actually for the specified architecture, then we + // short circuit early + match self.data().abi_arch { + Archs(a) if a & arch.bit() == 0 => return None, + Archs(_) | RustArch | AllArch => {} + } + // Transform this ABI as appropriate for the requested os/arch + // combination. + Some(match (*self, os, arch) { (System, OsWin32, X86) => Stdcall, (System, _, _) => C, (me, _, _) => me, - } + }) } } @@ -151,138 +153,9 @@ impl Architecture { } } -impl AbiSet { - pub fn from(abi: Abi) -> AbiSet { - AbiSet { bits: (1 << abi.index()) } - } - - #[inline] - pub fn Rust() -> AbiSet { - AbiSet::from(Rust) - } - - #[inline] - pub fn C() -> AbiSet { - AbiSet::from(C) - } - - #[inline] - pub fn Intrinsic() -> AbiSet { - AbiSet::from(RustIntrinsic) - } - - pub fn default() -> AbiSet { - AbiSet::C() - } - - pub fn empty() -> AbiSet { - AbiSet { bits: 0 } - } - - #[inline] - pub fn is_rust(&self) -> bool { - self.bits == 1 << Rust.index() - } - - #[inline] - pub fn is_c(&self) -> bool { - self.bits == 1 << C.index() - } - - #[inline] - pub fn is_intrinsic(&self) -> bool { - self.bits == 1 << RustIntrinsic.index() - } - - pub fn contains(&self, abi: Abi) -> bool { - (self.bits & (1 << abi.index())) != 0 - } - - pub fn subset_of(&self, other_abi_set: AbiSet) -> bool { - (self.bits & other_abi_set.bits) == self.bits - } - - pub fn add(&mut self, abi: Abi) { - self.bits |= 1 << abi.index(); - } - - pub fn each(&self, op: |abi: Abi| -> bool) -> bool { - each_abi(|abi| !self.contains(abi) || op(abi)) - } - - pub fn is_empty(&self) -> bool { - self.bits == 0 - } - - pub fn for_target(&self, os: Os, arch: Architecture) -> Option { - // NB---Single platform ABIs come first - - let mut res = None; - - self.each(|abi| { - let data = abi.data(); - match data.abi_arch { - Archs(a) if (a & arch.bit()) != 0 => { res = Some(abi); false } - Archs(_) => { true } - RustArch | AllArch => { res = Some(abi); false } - } - }); - - res.map(|r| r.for_target(os, arch)) - } - - pub fn check_valid(&self) -> Option<(Abi, Abi)> { - let mut abis = Vec::new(); - self.each(|abi| { abis.push(abi); true }); - - for (i, abi) in abis.iter().enumerate() { - let data = abi.data(); - for other_abi in abis.slice(0, i).iter() { - let other_data = other_abi.data(); - debug!("abis=({:?},{:?}) datas=({:?},{:?})", - abi, data.abi_arch, - other_abi, other_data.abi_arch); - match (&data.abi_arch, &other_data.abi_arch) { - (&AllArch, &AllArch) => { - // Two cross-architecture ABIs - return Some((*abi, *other_abi)); - } - (_, &RustArch) | - (&RustArch, _) => { - // Cannot combine Rust or Rust-Intrinsic with - // anything else. - return Some((*abi, *other_abi)); - } - (&Archs(is), &Archs(js)) if (is & js) != 0 => { - // Two ABIs for same architecture - return Some((*abi, *other_abi)); - } - _ => {} - } - } - } - - return None; - } -} - impl fmt::Show for Abi { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.data().name.fmt(f) - } -} - -impl fmt::Show for AbiSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f.buf, "\"")); - let mut first = true; - self.each(|abi| { - if first { first = false; } - else { let _ = write!(f.buf, " "); } - let _ = write!(f.buf, "{}", abi.data().name); - true - }); - write!(f.buf, "\"") + write!(f.buf, "\"{}\"", self.name()) } } @@ -304,95 +177,6 @@ fn lookup_baz() { assert!(abi.is_none()); } -#[cfg(test)] -fn cannot_combine(n: Abi, m: Abi) { - let mut set = AbiSet::empty(); - set.add(n); - set.add(m); - match set.check_valid() { - Some((a, b)) => { - assert!((n == a && m == b) || - (m == a && n == b)); - } - None => { - fail!("invalid match not detected"); - } - } -} - -#[cfg(test)] -fn can_combine(n: Abi, m: Abi) { - let mut set = AbiSet::empty(); - set.add(n); - set.add(m); - match set.check_valid() { - Some((_, _)) => { - fail!("valid match declared invalid"); - } - None => {} - } -} - -#[test] -fn cannot_combine_cdecl_and_stdcall() { - cannot_combine(Cdecl, Stdcall); -} - -#[test] -fn cannot_combine_c_and_rust() { - cannot_combine(C, Rust); -} - -#[test] -fn cannot_combine_rust_and_cdecl() { - cannot_combine(Rust, Cdecl); -} - -#[test] -fn cannot_combine_rust_intrinsic_and_cdecl() { - cannot_combine(RustIntrinsic, Cdecl); -} - -#[test] -fn can_combine_system_and_cdecl() { - can_combine(System, Cdecl); -} - -#[test] -fn can_combine_c_and_stdcall() { - can_combine(C, Stdcall); -} - -#[test] -fn can_combine_aapcs_and_stdcall() { - can_combine(Aapcs, Stdcall); -} - -#[test] -fn abi_to_str_stdcall_aaps() { - let mut set = AbiSet::empty(); - set.add(Aapcs); - set.add(Stdcall); - assert!(set.to_str() == ~"\"stdcall aapcs\""); -} - -#[test] -fn abi_to_str_c_aaps() { - let mut set = AbiSet::empty(); - set.add(Aapcs); - set.add(C); - debug!("set = {}", set.to_str()); - assert!(set.to_str() == ~"\"aapcs C\""); -} - -#[test] -fn abi_to_str_rust() { - let mut set = AbiSet::empty(); - set.add(Rust); - debug!("set = {}", set.to_str()); - assert!(set.to_str() == ~"\"Rust\""); -} - #[test] fn indices_are_correct() { for (i, abi_data) in AbiDatas.iter().enumerate() { @@ -407,30 +191,14 @@ fn indices_are_correct() { assert_eq!(ArmBits, bits); } -#[cfg(test)] -fn get_arch(abis: &[Abi], os: Os, arch: Architecture) -> Option { - let mut set = AbiSet::empty(); - for &abi in abis.iter() { - set.add(abi); - } - set.for_target(os, arch) -} - -#[test] -fn pick_multiplatform() { - assert_eq!(get_arch([C, Cdecl], OsLinux, X86), Some(Cdecl)); - assert_eq!(get_arch([C, Cdecl], OsLinux, X86_64), Some(Cdecl)); - assert_eq!(get_arch([C, Cdecl], OsLinux, Arm), Some(C)); -} - #[test] fn pick_uniplatform() { - assert_eq!(get_arch([Stdcall], OsLinux, X86), Some(Stdcall)); - assert_eq!(get_arch([Stdcall], OsLinux, Arm), None); - assert_eq!(get_arch([System], OsLinux, X86), Some(C)); - assert_eq!(get_arch([System], OsWin32, X86), Some(Stdcall)); - assert_eq!(get_arch([System], OsWin32, X86_64), Some(C)); - assert_eq!(get_arch([System], OsWin32, Arm), Some(C)); - assert_eq!(get_arch([Stdcall], OsWin32, X86), Some(Stdcall)); - assert_eq!(get_arch([Stdcall], OsWin32, X86_64), Some(Stdcall)); + assert_eq!(Stdcall.for_arch(OsLinux, X86), Some(Stdcall)); + assert_eq!(Stdcall.for_arch(OsLinux, Arm), None); + assert_eq!(System.for_arch(OsLinux, X86), Some(C)); + assert_eq!(System.for_arch(OsWin32, X86), Some(Stdcall)); + assert_eq!(System.for_arch(OsWin32, X86_64), Some(C)); + assert_eq!(System.for_arch(OsWin32, Arm), Some(C)); + assert_eq!(Stdcall.for_arch(OsWin32, X86), Some(Stdcall)); + assert_eq!(Stdcall.for_arch(OsWin32, X86_64), Some(Stdcall)); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3a9cdfb56e3..4612f8e6673 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -11,7 +11,7 @@ // The Rust abstract syntax tree. use codemap::{Span, Spanned, DUMMY_SP}; -use abi::AbiSet; +use abi::Abi; use ast_util; use owned_slice::OwnedSlice; use parse::token::{InternedString, special_idents, str_to_ident}; @@ -807,7 +807,7 @@ pub struct ClosureTy { #[deriving(Eq, TotalEq, Encodable, Decodable, Hash)] pub struct BareFnTy { pub purity: Purity, - pub abis: AbiSet, + pub abi: Abi, pub lifetimes: Vec, pub decl: P } @@ -941,7 +941,7 @@ pub struct Mod { #[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] pub struct ForeignMod { - pub abis: AbiSet, + pub abi: Abi, pub view_items: Vec, pub items: Vec<@ForeignItem>, } @@ -1119,7 +1119,7 @@ pub struct Item { #[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] pub enum Item_ { ItemStatic(P, Mutability, @Expr), - ItemFn(P, Purity, AbiSet, Generics, P), + ItemFn(P, Purity, Abi, Generics, P), ItemMod(Mod), ItemForeignMod(ForeignMod), ItemTy(P, Generics), diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index f07b0e71c1c..e098dcd99fd 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::AbiSet; +use abi; use ast::*; use ast_util; use codemap::Span; @@ -224,19 +224,19 @@ impl Map { } } - pub fn get_foreign_abis(&self, id: NodeId) -> AbiSet { + pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi { let parent = self.get_parent(id); - let abis = match self.find_entry(parent) { + let abi = match self.find_entry(parent) { Some(EntryItem(_, i)) => match i.node { - ItemForeignMod(ref nm) => Some(nm.abis), + ItemForeignMod(ref nm) => Some(nm.abi), _ => None }, // Wrong but OK, because the only inlined foreign items are intrinsics. - Some(RootInlinedParent(_)) => Some(AbiSet::Intrinsic()), + Some(RootInlinedParent(_)) => Some(abi::RustIntrinsic), _ => None }; - match abis { - Some(abis) => abis, + match abi { + Some(abi) => abi, None => fail!("expected foreign mod or inlined parent, found {}", self.node_to_str(parent)) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 489af0fc2d4..ef62f0a01f6 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::AbiSet; +use abi; use ast::{P, Ident}; use ast; use ast_util; @@ -826,7 +826,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { Vec::new(), ast::ItemFn(self.fn_decl(inputs, output), ast::ImpureFn, - AbiSet::Rust(), + abi::Rust, generics, body)) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 03963219d52..06bf892771d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -170,7 +170,7 @@ pub trait Folder { TyBareFn(@BareFnTy { lifetimes: f.lifetimes.iter().map(|l| fold_lifetime(l, self)).collect(), purity: f.purity, - abis: f.abis, + abi: f.abi, decl: self.fold_fn_decl(f.decl) }) } @@ -198,7 +198,7 @@ pub trait Folder { fn fold_foreign_mod(&mut self, nm: &ForeignMod) -> ForeignMod { ast::ForeignMod { - abis: nm.abis, + abi: nm.abi, view_items: nm.view_items .iter() .map(|x| self.fold_view_item(x)) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 76126e6780a..dbb85972774 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -657,7 +657,7 @@ mod test { variadic: false }), ast::ImpureFn, - abi::AbiSet::Rust(), + abi::Rust, ast::Generics{ // no idea on either of these: lifetimes: Vec::new(), ty_params: OwnedSlice::empty(), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b3e488a464d..2d78bfe5694 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -11,7 +11,6 @@ #![macro_escape] use abi; -use abi::AbiSet; use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil}; use ast::{BareFnTy, ClosureTy}; use ast::{RegionTyParamBound, TraitTyParamBound}; @@ -873,17 +872,17 @@ impl<'a> Parser<'a> { */ - let abis = if self.eat_keyword(keywords::Extern) { - self.parse_opt_abis().unwrap_or(AbiSet::C()) + let abi = if self.eat_keyword(keywords::Extern) { + self.parse_opt_abi().unwrap_or(abi::C) } else { - AbiSet::Rust() + abi::Rust }; let purity = self.parse_unsafety(); self.expect_keyword(keywords::Fn); let (decl, lifetimes) = self.parse_ty_fn_decl(true); return TyBareFn(@BareFnTy { - abis: abis, + abi: abi, purity: purity, lifetimes: lifetimes, decl: decl @@ -3770,11 +3769,11 @@ impl<'a> Parser<'a> { } // parse an item-position function declaration. - fn parse_item_fn(&mut self, purity: Purity, abis: AbiSet) -> ItemInfo { + fn parse_item_fn(&mut self, purity: Purity, abi: abi::Abi) -> ItemInfo { let (ident, generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(false); let (inner_attrs, body) = self.parse_inner_attrs_and_block(); - (ident, ItemFn(decl, purity, abis, generics, body), Some(inner_attrs)) + (ident, ItemFn(decl, purity, abi, generics, body), Some(inner_attrs)) } // parse a method in a trait impl, starting with `attrs` attributes. @@ -4237,7 +4236,7 @@ impl<'a> Parser<'a> { // at this point, this is essentially a wrapper for // parse_foreign_items. fn parse_foreign_mod_items(&mut self, - abis: AbiSet, + abi: abi::Abi, first_item_attrs: Vec ) -> ForeignMod { let ParsedItemsAndViewItems { @@ -4252,7 +4251,7 @@ impl<'a> Parser<'a> { } assert!(self.token == token::RBRACE); ast::ForeignMod { - abis: abis, + abi: abi, view_items: view_items, items: foreign_items } @@ -4310,17 +4309,17 @@ impl<'a> Parser<'a> { /// extern {} fn parse_item_foreign_mod(&mut self, lo: BytePos, - opt_abis: Option, + opt_abi: Option, visibility: Visibility, attrs: Vec ) -> ItemOrViewItem { self.expect(&token::LBRACE); - let abis = opt_abis.unwrap_or(AbiSet::C()); + let abi = opt_abi.unwrap_or(abi::C); let (inner, next) = self.parse_inner_attrs_and_next(); - let m = self.parse_foreign_mod_items(abis, next); + let m = self.parse_foreign_mod_items(abi, next); self.expect(&token::RBRACE); let item = self.mk_item(lo, @@ -4440,45 +4439,29 @@ impl<'a> Parser<'a> { // Parses a string as an ABI spec on an extern type or module. Consumes // the `extern` keyword, if one is found. - fn parse_opt_abis(&mut self) -> Option { + fn parse_opt_abi(&mut self) -> Option { match self.token { - token::LIT_STR(s) - | token::LIT_STR_RAW(s, _) => { + token::LIT_STR(s) | token::LIT_STR_RAW(s, _) => { self.bump(); let identifier_string = token::get_ident(s); let the_string = identifier_string.get(); - let mut abis = AbiSet::empty(); - for word in the_string.words() { - match abi::lookup(word) { - Some(abi) => { - if abis.contains(abi) { - self.span_err( - self.span, - format!("ABI `{}` appears twice", - word)); - } else { - abis.add(abi); - } - } - - None => { - self.span_err( - self.span, - format!("illegal ABI: \ - expected one of [{}], \ - found `{}`", - abi::all_names().connect(", "), - word)); - } - } - } - Some(abis) + match abi::lookup(the_string) { + Some(abi) => Some(abi), + None => { + self.span_err( + self.span, + format!("illegal ABI: \ + expected one of [{}], \ + found `{}`", + abi::all_names().connect(", "), + the_string)); + None + } + } } - _ => { - None - } - } + _ => None, + } } // parse one of the items or view items allowed by the @@ -4531,13 +4514,13 @@ impl<'a> Parser<'a> { return self.parse_item_extern_crate(lo, visibility, attrs); } - let opt_abis = self.parse_opt_abis(); + let opt_abi = self.parse_opt_abi(); if self.eat_keyword(keywords::Fn) { // EXTERN FUNCTION ITEM - let abis = opt_abis.unwrap_or(AbiSet::C()); + let abi = opt_abi.unwrap_or(abi::C); let (ident, item_, extra_attrs) = - self.parse_item_fn(ExternFn, abis); + self.parse_item_fn(ExternFn, abi); let item = self.mk_item(lo, self.last_span.hi, ident, @@ -4546,7 +4529,7 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return IoviItem(item); } else if self.token == token::LBRACE { - return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs); + return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs); } let token_str = self.this_token_to_str(); @@ -4572,7 +4555,7 @@ impl<'a> Parser<'a> { // FUNCTION ITEM self.bump(); let (ident, item_, extra_attrs) = - self.parse_item_fn(ImpureFn, AbiSet::Rust()); + self.parse_item_fn(ImpureFn, abi::Rust); let item = self.mk_item(lo, self.last_span.hi, ident, @@ -4587,7 +4570,7 @@ impl<'a> Parser<'a> { self.bump(); self.expect_keyword(keywords::Fn); let (ident, item_, extra_attrs) = - self.parse_item_fn(UnsafeFn, AbiSet::Rust()); + self.parse_item_fn(UnsafeFn, abi::Rust); let item = self.mk_item(lo, self.last_span.hi, ident, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 98a3ff30916..1eee0fb87d6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::AbiSet; +use abi; use ast::{P, RegionTyParamBound, TraitTyParamBound, Required, Provided}; use ast; use ast_util; @@ -190,7 +190,7 @@ pub fn fun_to_str(decl: &ast::FnDecl, purity: ast::Purity, name: ast::Ident, opt_explicit_self: Option, generics: &ast::Generics) -> ~str { to_str(|s| { - try!(s.print_fn(decl, Some(purity), AbiSet::Rust(), + try!(s.print_fn(decl, Some(purity), abi::Rust, name, generics, opt_explicit_self, ast::Inherited)); try!(s.end()); // Close the head box s.end() // Close the outer box @@ -478,7 +478,7 @@ impl<'a> State<'a> { lifetimes: f.lifetimes.clone(), ty_params: OwnedSlice::empty() }; - try!(self.print_ty_fn(Some(f.abis), None, &None, + try!(self.print_ty_fn(Some(f.abi), None, &None, f.purity, ast::Many, f.decl, None, &None, Some(&generics), None)); } @@ -524,7 +524,7 @@ impl<'a> State<'a> { try!(self.print_outer_attributes(item.attrs.as_slice())); match item.node { ast::ForeignItemFn(decl, ref generics) => { - try!(self.print_fn(decl, None, AbiSet::Rust(), item.ident, generics, + try!(self.print_fn(decl, None, abi::Rust, item.ident, generics, None, item.vis)); try!(self.end()); // end head-ibox try!(word(&mut self.s, ";")); @@ -590,7 +590,7 @@ impl<'a> State<'a> { } ast::ItemForeignMod(ref nmod) => { try!(self.head("extern")); - try!(self.word_nbsp(nmod.abis.to_str())); + try!(self.word_nbsp(nmod.abi.to_str())); try!(self.bopen()); try!(self.print_foreign_mod(nmod, item.attrs.as_slice())); try!(self.bclose(item.span)); @@ -883,7 +883,7 @@ impl<'a> State<'a> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(meth.span.lo)); try!(self.print_outer_attributes(meth.attrs.as_slice())); - try!(self.print_fn(meth.decl, Some(meth.purity), AbiSet::Rust(), + try!(self.print_fn(meth.decl, Some(meth.purity), abi::Rust, meth.ident, &meth.generics, Some(meth.explicit_self.node), meth.vis)); try!(word(&mut self.s, " ")); @@ -1717,14 +1717,14 @@ impl<'a> State<'a> { pub fn print_fn(&mut self, decl: &ast::FnDecl, purity: Option, - abis: AbiSet, + abi: abi::Abi, name: ast::Ident, generics: &ast::Generics, opt_explicit_self: Option, vis: ast::Visibility) -> IoResult<()> { try!(self.head("")); - try!(self.print_fn_header_info(opt_explicit_self, purity, abis, - ast::Many, None, vis)); + try!(self.print_fn_header_info(opt_explicit_self, purity, abi, + ast::Many, None, vis)); try!(self.nbsp()); try!(self.print_ident(name)); try!(self.print_generics(generics)); @@ -2016,7 +2016,7 @@ impl<'a> State<'a> { } pub fn print_ty_fn(&mut self, - opt_abis: Option, + opt_abi: Option, opt_sigil: Option, opt_region: &Option, purity: ast::Purity, @@ -2034,14 +2034,14 @@ impl<'a> State<'a> { if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once { try!(word(&mut self.s, "proc")); } else if opt_sigil == Some(ast::BorrowedSigil) { - try!(self.print_extern_opt_abis(opt_abis)); + try!(self.print_extern_opt_abi(opt_abi)); for lifetime in opt_region.iter() { try!(self.print_lifetime(lifetime)); } try!(self.print_purity(purity)); try!(self.print_onceness(onceness)); } else { - try!(self.print_opt_abis_and_extern_if_nondefault(opt_abis)); + try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi)); try!(self.print_opt_sigil(opt_sigil)); try!(self.print_opt_lifetime(opt_region)); try!(self.print_purity(purity)); @@ -2303,24 +2303,25 @@ impl<'a> State<'a> { } } - pub fn print_opt_abis_and_extern_if_nondefault(&mut self, - opt_abis: Option) + pub fn print_opt_abi_and_extern_if_nondefault(&mut self, + opt_abi: Option) -> IoResult<()> { - match opt_abis { - Some(abis) if !abis.is_rust() => { + match opt_abi { + Some(abi::Rust) => Ok(()), + Some(abi) => { try!(self.word_nbsp("extern")); - self.word_nbsp(abis.to_str()) + self.word_nbsp(abi.to_str()) } - Some(_) | None => Ok(()) + None => Ok(()) } } - pub fn print_extern_opt_abis(&mut self, - opt_abis: Option) -> IoResult<()> { - match opt_abis { - Some(abis) => { + pub fn print_extern_opt_abi(&mut self, + opt_abi: Option) -> IoResult<()> { + match opt_abi { + Some(abi) => { try!(self.word_nbsp("extern")); - self.word_nbsp(abis.to_str()) + self.word_nbsp(abi.to_str()) } None => Ok(()) } @@ -2339,15 +2340,15 @@ impl<'a> State<'a> { pub fn print_fn_header_info(&mut self, _opt_explicit_self: Option, opt_purity: Option, - abis: AbiSet, + abi: abi::Abi, onceness: ast::Onceness, opt_sigil: Option, vis: ast::Visibility) -> IoResult<()> { try!(word(&mut self.s, visibility_qualified(vis, ""))); - if abis != AbiSet::Rust() { + if abi != abi::Rust { try!(self.word_nbsp("extern")); - try!(self.word_nbsp(abis.to_str())); + try!(self.word_nbsp(abi.to_str())); if opt_purity != Some(ast::ExternFn) { try!(self.print_opt_purity(opt_purity)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index de3eb1b9b8d..eb03bb1f0bb 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::AbiSet; +use abi::Abi; use ast::*; use ast; use codemap::Span; @@ -29,7 +29,7 @@ use owned_slice::OwnedSlice; pub enum FnKind<'a> { // fn foo() or extern "Abi" fn foo() - FkItemFn(Ident, &'a Generics, Purity, AbiSet), + FkItemFn(Ident, &'a Generics, Purity, Abi), // fn foo(&self) FkMethod(Ident, &'a Generics, &'a Method), From 487fa9568b69753fecb74a8460109239f4bf3631 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 3 Apr 2014 14:09:16 -0700 Subject: [PATCH 15/15] Test fixes from the rollup --- src/libstd/rt/global_heap.rs | 10 +++++----- src/libsyntax/abi.rs | 16 ++++++++-------- src/test/bench/rt-spawn-rate.rs | 10 ++++++++++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 3917857e1af..5c1b6cd4791 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -64,16 +64,16 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 { } } -// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size -// allocations can point to this `static`. It would be incorrect to use a null -// pointer, due to enums assuming types like unique pointers are never null. -static EMPTY: () = (); - /// The allocator for unique pointers without contained managed pointers. #[cfg(not(test))] #[lang="exchange_malloc"] #[inline] pub unsafe fn exchange_malloc(size: uint) -> *mut u8 { + // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size + // allocations can point to this `static`. It would be incorrect to use a null + // pointer, due to enums assuming types like unique pointers are never null. + static EMPTY: () = (); + if size == 0 { &EMPTY as *() as *mut u8 } else { diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index a40899de931..17251d31351 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -193,12 +193,12 @@ fn indices_are_correct() { #[test] fn pick_uniplatform() { - assert_eq!(Stdcall.for_arch(OsLinux, X86), Some(Stdcall)); - assert_eq!(Stdcall.for_arch(OsLinux, Arm), None); - assert_eq!(System.for_arch(OsLinux, X86), Some(C)); - assert_eq!(System.for_arch(OsWin32, X86), Some(Stdcall)); - assert_eq!(System.for_arch(OsWin32, X86_64), Some(C)); - assert_eq!(System.for_arch(OsWin32, Arm), Some(C)); - assert_eq!(Stdcall.for_arch(OsWin32, X86), Some(Stdcall)); - assert_eq!(Stdcall.for_arch(OsWin32, X86_64), Some(Stdcall)); + assert_eq!(Stdcall.for_target(OsLinux, X86), Some(Stdcall)); + assert_eq!(Stdcall.for_target(OsLinux, Arm), None); + assert_eq!(System.for_target(OsLinux, X86), Some(C)); + assert_eq!(System.for_target(OsWin32, X86), Some(Stdcall)); + assert_eq!(System.for_target(OsWin32, X86_64), Some(C)); + assert_eq!(System.for_target(OsWin32, Arm), Some(C)); + assert_eq!(Stdcall.for_target(OsWin32, X86), Some(Stdcall)); + assert_eq!(Stdcall.for_target(OsWin32, X86_64), Some(Stdcall)); } diff --git a/src/test/bench/rt-spawn-rate.rs b/src/test/bench/rt-spawn-rate.rs index 5f445de069c..4f07660779b 100644 --- a/src/test/bench/rt-spawn-rate.rs +++ b/src/test/bench/rt-spawn-rate.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![no_start] + +extern crate green; +extern crate rustuv; + use std::task::spawn; use std::os; use std::uint; @@ -15,6 +20,11 @@ use std::uint; // Very simple spawn rate test. Spawn N tasks that do nothing and // return. +#[start] +fn start(argc: int, argv: **u8) -> int { + green::start(argc, argv, rustuv::event_loop, main) +} + fn main() { let args = os::args();