diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index e2bcc491d1b1..3882e4ca3b3f 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -265,7 +265,7 @@ CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This, { // Cheerp: if the base class has no members create a bitcast with cheerp specific intrinsic if(Base->isEmpty() || Offset.isZero()) - return GenerateUpcastCollapsed(This, ConvertType(Base), 0); + return GenerateUpcastCollapsed(This, ConvertType(Base), This.getAddressSpace()); else { // Get the layout. @@ -565,7 +565,7 @@ CodeGenFunction::GenerateUpcast(Address Value, //Cheerp: Check if the type is the expected one. If not create a builtin to handle this. //This may happen when empty base classes are used if(Value.getType()!=BasePtrTy) - Value = GenerateUpcastCollapsed(Value, BasePtrTy, 0); + Value = GenerateUpcastCollapsed(Value, BasePtrTy, Value.getAddressSpace()); return Value; } @@ -583,19 +583,19 @@ CodeGenFunction::GenerateDowncast(Address Value, const CXXRecordDecl *Derived, llvm::Value* BaseIdOffset) { - QualType DerivedTy = - getContext().getCanonicalType(getContext().getTagDeclType(Derived)); - llvm::Type *DerivedPtrTy = ConvertType(DerivedTy); + llvm::Type *DerivedTy = + ConvertType(getContext().getCanonicalType(getContext().getTagDeclType(Derived))); + llvm::Type *DerivedPtrTy = DerivedTy->getPointerTo(Value.getAddressSpace()); - llvm::Type* types[] = { DerivedPtrTy->getPointerTo(), Value.getType() }; + llvm::Type* types[] = { DerivedPtrTy, Value.getType() }; llvm::Function* intrinsic = llvm::Intrinsic::getDeclaration(&CGM.getModule(), llvm::Intrinsic::cheerp_downcast, types); llvm::CallBase* CB = Builder.CreateCall(intrinsic, {Value.getPointer(), BaseIdOffset}); CB->addParamAttr(0, llvm::Attribute::get(CB->getContext(), llvm::Attribute::ElementType, Value.getElementType())); - CB->addRetAttr(llvm::Attribute::get(CB->getContext(), llvm::Attribute::ElementType, DerivedPtrTy)); - return Address(CB, DerivedPtrTy, Value.getAlignment()); + CB->addRetAttr(llvm::Attribute::get(CB->getContext(), llvm::Attribute::ElementType, DerivedTy)); + return Address(CB, DerivedTy, Value.getAlignment()); } llvm::Value * diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index df14e74106e6..6d25f5f0b8a4 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1553,11 +1553,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { allocaAlignment = alignment; } + uint32_t AS = getTarget().isByteAddressable()? 0 : getContext().getTargetAddressSpace(Ty.getAddressSpace()); // Create the alloca. Note that we set the name separately from // building the instruction so that it's there even in no-asserts // builds. address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName(), - /*ArraySize=*/nullptr, &AllocaAddr); + /*ArraySize=*/nullptr, &AllocaAddr, AS); // Don't emit lifetime markers for MSVC catch parameters. The lifetime of // the catch parameter starts in the catchpad instruction, and we can't diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 1e14628fe5e9..52b6ed222bce 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -68,8 +68,9 @@ llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) { Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits Align, const Twine &Name, - llvm::Value *ArraySize) { - auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); + llvm::Value *ArraySize, + uint32_t AS) { + auto Alloca = CreateTempAlloca(Ty, Name, ArraySize, AS); Alloca->setAlignment(Align.getAsAlign()); return Address(Alloca, Ty, Align); } @@ -79,8 +80,9 @@ Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, const Twine &Name, llvm::Value *ArraySize, - Address *AllocaAddr) { - auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); + Address *AllocaAddr, + uint32_t AS) { + auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize, AS); if (AllocaAddr) *AllocaAddr = Alloca; llvm::Value *V = Alloca.getPointer(); @@ -109,10 +111,11 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, /// insertion point of the builder. llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, const Twine &Name, - llvm::Value *ArraySize) { + llvm::Value *ArraySize, + uint32_t AS) { if (ArraySize) return Builder.CreateAlloca(Ty, ArraySize, Name); - return new llvm::AllocaInst(Ty, CGM.getDataLayout().getAllocaAddrSpace(), + return new llvm::AllocaInst(Ty, AS == 0? CGM.getDataLayout().getAllocaAddrSpace() : AS, ArraySize, Name, AllocaInsertPt); } @@ -4498,7 +4501,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName()); } else if (!CGM.getTarget().isByteAddressable() && CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field) == 0xffffffff) { // Cheerp: If the first member is a struct we want to collapse it into the parent, and we use upcast_collapsed to access it - addr = GenerateUpcastCollapsed(addr, CGM.getTypes().ConvertTypeForMem(FieldType), 0); + addr = GenerateUpcastCollapsed(addr, CGM.getTypes().ConvertTypeForMem(FieldType), addr.getAddressSpace()); } else { if (!IsInPreservedAIRegion && (!getDebugInfo() || !rec->hasAttr())) diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 626ce57e3d53..b5681650de29 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1682,6 +1682,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { if (!getTarget().isByteAddressable() && !asmjs) { const CastExpr* castExpr = dyn_cast(arg); + if (castExpr && castExpr->getCastKind() == CK_AddressSpaceConversion) { + // Peel the address space cast. The `new` expression returns a pointer to + // a non-default AS, but the placement new definition returns plain void*. + arg = castExpr->getSubExpr(); + castExpr = dyn_cast(arg); + } if (castExpr == NULL || castExpr->getSubExpr()->getType()->getPointeeType().getCanonicalType().getUnqualifiedType()!=allocType.getCanonicalType().getUnqualifiedType()) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index ea6d1e1731a4..cff3c2290f84 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2586,14 +2586,17 @@ class CodeGenFunction : public CodeGenTypeCache { /// The cast is not performaed in CreateTempAllocaWithoutCast. This is /// more efficient if the caller knows that the address will not be exposed. llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); + llvm::Value *ArraySize = nullptr, + uint32_t AS = 0); Address CreateTempAlloca(llvm::Type *Ty, CharUnits align, const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr, - Address *Alloca = nullptr); + Address *Alloca = nullptr, + uint32_t AS = 0); Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); + llvm::Value *ArraySize = nullptr, + uint32_t AS = 0); /// CreateDefaultAlignedTempAlloca - This creates an alloca with the /// default ABI alignment of the given LLVM type. diff --git a/llvm/lib/CheerpUtils/TypeOptimizer.cpp b/llvm/lib/CheerpUtils/TypeOptimizer.cpp index 2ff096461569..d224ac12ec29 100644 --- a/llvm/lib/CheerpUtils/TypeOptimizer.cpp +++ b/llvm/lib/CheerpUtils/TypeOptimizer.cpp @@ -902,6 +902,13 @@ std::pair TypeOptimizer::rewriteConstant(Constant* C, bool r Constant* srcOperand = rewrittenOperand.first; return std::make_pair(ConstantExpr::getBitCast(srcOperand, newTypeInfo.mappedType), 0); } + case Instruction::AddrSpaceCast: + { + auto rewrittenOperand = rewriteConstant(CE->getOperand(0), false); + assert(rewrittenOperand.second == 0); + Constant* srcOperand = rewrittenOperand.first; + return std::make_pair(ConstantExpr::getPointerBitCastOrAddrSpaceCast(srcOperand, newTypeInfo.mappedType), 0); + } case Instruction::IntToPtr: { return std::make_pair(ConstantExpr::getIntToPtr(CE->getOperand(0), newTypeInfo.mappedType), 0); @@ -2085,6 +2092,7 @@ void TypeOptimizer::rewriteFunction(Function* F) break; } case Instruction::BitCast: + case Instruction::AddrSpaceCast: case Instruction::ExtractValue: case Instruction::InsertValue: case Instruction::IntToPtr: diff --git a/llvm/lib/CheerpUtils/Utility.cpp b/llvm/lib/CheerpUtils/Utility.cpp index 163d2a84256b..320589f80ac2 100644 --- a/llvm/lib/CheerpUtils/Utility.cpp +++ b/llvm/lib/CheerpUtils/Utility.cpp @@ -501,6 +501,7 @@ bool InlineableCache::isInlineableImpl(const Instruction& I) case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::ShuffleVector: + case Instruction::AddrSpaceCast: return true; case Instruction::ExtractElement: case Instruction::InsertElement: diff --git a/llvm/lib/CheerpWriter/CheerpWriter.cpp b/llvm/lib/CheerpWriter/CheerpWriter.cpp index 516956e68e82..c98c0206cf34 100644 --- a/llvm/lib/CheerpWriter/CheerpWriter.cpp +++ b/llvm/lib/CheerpWriter/CheerpWriter.cpp @@ -2315,6 +2315,11 @@ void CheerpWriter::compileConstantExpr(const ConstantExpr* ce, PARENT_PRIORITY p compileBitCast(ce, k, parentPrio); break; } + case Instruction::AddrSpaceCast: + { + compileOperand(ce->getOperand(0), parentPrio); + break; + } case Instruction::IntToPtr: { compileOperand(ce->getOperand(0), parentPrio); @@ -3740,6 +3745,11 @@ CheerpWriter::COMPILE_INSTRUCTION_FEEDBACK CheerpWriter::compileInlineableInstru compileBitCast(&I, k, parentPrio); return COMPILE_OK; } + case Instruction::AddrSpaceCast: + { + compileOperand(I.getOperand(0), parentPrio); + return COMPILE_OK; + } case Instruction::FPToSI: case Instruction::FPToUI: { diff --git a/llvm/lib/CheerpWriter/PreExecute.cpp b/llvm/lib/CheerpWriter/PreExecute.cpp index 47239ba4eab3..e0a678a351c4 100644 --- a/llvm/lib/CheerpWriter/PreExecute.cpp +++ b/llvm/lib/CheerpWriter/PreExecute.cpp @@ -666,7 +666,7 @@ Constant* PreExecute::findPointerFromGlobal(const DataLayout* DL, Constant* GEP = ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Indices); assert(GEP->getType() == typeFound->getPointerTo(GEP->getType()->getPointerAddressSpace())); if(GEP->getType() != memType) - return ConstantExpr::getBitCast(GEP, memType); + return ConstantExpr::getPointerBitCastOrAddrSpaceCast(GEP, memType); return GEP; } diff --git a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index a79c60d5593f..9f029f610ff9 100644 --- a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -801,6 +801,9 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { } return GV; } + case Instruction::AddrSpaceCast: { + return getConstantValue(Op0); + } case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: diff --git a/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp index f668ccd655a2..918a612899e5 100644 --- a/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -1777,6 +1777,11 @@ GenericValue Interpreter::executeBitCastInst(Value *SrcVal, Type *DstTy, return Dest; } +GenericValue Interpreter::executeAddrSpaceCastInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF) { + return getOperandValue(SrcVal, SF); +} + void Interpreter::visitTruncInst(TruncInst &I) { ExecutionContext &SF = ECStack.back(); SetValue(&I, executeTruncInst(I.getOperand(0), I.getType(), SF), SF); @@ -1837,6 +1842,11 @@ void Interpreter::visitBitCastInst(BitCastInst &I) { SetValue(&I, executeBitCastInst(I.getOperand(0), I.getType(), SF), SF); } +void Interpreter::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeAddrSpaceCastInst(I.getOperand(0), I.getType(), SF), SF); +} + void Interpreter::visitFreezeInst(FreezeInst &I) { ExecutionContext &SF = ECStack.back(); SetValue(&I, executeFreezeInst(I.getOperand(0), SF), SF); @@ -2223,6 +2233,8 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, return executeIntToPtrInst(CE->getOperand(0), CE->getType(), SF); case Instruction::BitCast: return executeBitCastInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::AddrSpaceCast: + return executeAddrSpaceCastInst(CE->getOperand(0), CE->getType(), SF); case Instruction::GetElementPtr: return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE), gep_type_end(CE), SF); diff --git a/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h index 132d2830c0dc..643ec1c8f7d7 100644 --- a/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -200,6 +200,7 @@ class Interpreter : public ExecutionEngine, public InstVisitor { void visitPtrToIntInst(PtrToIntInst &I); void visitIntToPtrInst(IntToPtrInst &I); void visitBitCastInst(BitCastInst &I); + void visitAddrSpaceCastInst(AddrSpaceCastInst &I); void visitFreezeInst(FreezeInst &I); void visitSelectInst(SelectInst &I); @@ -304,6 +305,8 @@ class Interpreter : public ExecutionEngine, public InstVisitor { ExecutionContext &SF); GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); + GenericValue executeAddrSpaceCastInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); GenericValue executeFreezeInst(Value *SrcVal, ExecutionContext &SF); GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, Type *Ty, ExecutionContext &SF);