Changeset 4253
- Timestamp:
- Oct 20, 2014, 12:57:30 PM (4 years ago)
- Location:
- icGREP/icgrep-devel/icgrep
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
icGREP/icgrep-devel/icgrep/compiler.cpp
r4249 r4253 84 84 } 85 85 86 // note: system is clumbersome at the moment; this needsto be done AFTER toUTF8.86 // note: system is clumbersome at the moment; this ought to be done AFTER toUTF8. 87 87 nameMap.addPredefined("LineFeed", makeCC(0x0A)); 88 88 -
icGREP/icgrep-devel/icgrep/pablo/pablo_compiler.cpp
r4252 r4253 83 83 , mXi128Vect(VectorType::get(IntegerType::get(mMod->getContext(), 128), BLOCK_SIZE / 128)) 84 84 , mBasisBitsInputPtr(nullptr) 85 , mOutputPtr(nullptr)86 85 , mCarryQueueIdx(0) 87 , m ptr_carry_q(nullptr)86 , mCarryQueuePtr(nullptr) 88 87 , mCarryQueueSize(0) 89 88 , mZeroInitializer(ConstantAggregateZero::get(mXi64Vect)) 90 89 , mOneInitializer(ConstantVector::getAllOnesValue(mXi64Vect)) 91 , mFunc Ty_0(nullptr)90 , mFunctionType(nullptr) 92 91 , mFunc_process_block(nullptr) 93 92 , mBasisBitsAddr(nullptr) 94 , mPtr_carry_q_addr(nullptr) 95 , mPtr_output_addr(nullptr) 93 , mOutputAddrPtr(nullptr) 96 94 , mNameMap(nameMap) 97 95 { … … 147 145 } 148 146 149 LLVM_Gen_RetVal PabloCompiler::compile(const PabloBlock & cg_state)147 LLVM_Gen_RetVal PabloCompiler::compile(const PabloBlock & pb) 150 148 { 151 149 mCarryQueueSize = 0; 152 DeclareCallFunctions( cg_state.expressions());150 DeclareCallFunctions(pb.expressions()); 153 151 154 152 Function::arg_iterator args = mFunc_process_block->arg_begin(); 155 153 mBasisBitsAddr = args++; 156 154 mBasisBitsAddr->setName("basis_bits"); 157 m ptr_carry_q= args++;158 m ptr_carry_q->setName("carry_q");159 Value* ptr_output= args++;160 ptr_output->setName("output");155 mCarryQueuePtr = args++; 156 mCarryQueuePtr->setName("carry_q"); 157 mOutputAddrPtr = args++; 158 mOutputAddrPtr->setName("output"); 161 159 162 160 //Create the carry queue. … … 171 169 mMarkerMap.insert(make_pair(name, b.CreateGEP(mBasisBitsAddr, indices, name))); 172 170 } 173 mPtr_output_addr = new AllocaInst(mOutputPtr, "output.addr", mBasicBlock);174 new StoreInst(ptr_output, mPtr_output_addr, false, mBasicBlock);175 171 176 172 //Generate the IR instructions for the function. 177 SetReturnMarker(compileStatements( cg_state.expressions()), 0); // matches173 SetReturnMarker(compileStatements(pb.expressions()), 0); // matches 178 174 SetReturnMarker(GetMarker(mNameMap["LineFeed"]->getName()), 1); // line feeds 179 175 … … 257 253 258 254 //The output structure. 259 StructType * StructTy_struct_Output = mMod->getTypeByName("struct.Output");260 if (! StructTy_struct_Output) {261 StructTy_struct_Output = StructType::create(mMod->getContext(), "struct.Output");262 } 263 std::vector<Type*>StructTy_struct_Output_fields;264 StructTy_struct_Output_fields.push_back(mXi64Vect);265 StructTy_struct_Output_fields.push_back(mXi64Vect);266 if (StructTy_struct_Output->isOpaque()) {267 StructTy_struct_Output->setBody(StructTy_struct_Output_fields, /*isPacked=*/false);268 } 269 mOutputPtr = PointerType::get(StructTy_struct_Output, 0);255 StructType * outputStruct = mMod->getTypeByName("struct.Output"); 256 if (!outputStruct) { 257 outputStruct = StructType::create(mMod->getContext(), "struct.Output"); 258 } 259 if (outputStruct->isOpaque()) { 260 std::vector<Type*>StructTy_struct_Output_fields; 261 StructTy_struct_Output_fields.push_back(mXi64Vect); 262 StructTy_struct_Output_fields.push_back(mXi64Vect); 263 outputStruct->setBody(StructTy_struct_Output_fields, /*isPacked=*/false); 264 } 265 PointerType* outputStructPtr = PointerType::get(outputStruct, 0); 270 266 271 267 //The &output parameter. 272 FuncTy_0_args.push_back( mOutputPtr);273 274 mFunc Ty_0= FunctionType::get(268 FuncTy_0_args.push_back(outputStructPtr); 269 270 mFunctionType = FunctionType::get( 275 271 /*Result=*/Type::getVoidTy(mMod->getContext()), 276 272 /*Params=*/FuncTy_0_args, … … 360 356 if (!mFunc_process_block) { 361 357 mFunc_process_block = Function::Create( 362 /*Type=*/mFunc Ty_0,358 /*Type=*/mFunctionType, 363 359 /*Linkage=*/GlobalValue::ExternalLinkage, 364 360 /*Name=*/"process_block", mMod); … … 369 365 370 366 void PabloCompiler::DeclareCallFunctions(const ExpressionList & stmts) { 371 for (const PabloAST * stmt : stmts) { 372 if (const Assign * an = dyn_cast<const Assign>(stmt)) { 373 DeclareCallFunctions(an->getExpr()); 374 } 375 else if (const If * ifstmt = dyn_cast<const If>(stmt)) { 367 for (PabloAST * stmt : stmts) { 368 if (const Assign * assign = dyn_cast<Assign>(stmt)) { 369 DeclareCallFunctions(assign->getExpr()); 370 } 371 if (const Next * next = dyn_cast<Next>(stmt)) { 372 DeclareCallFunctions(next->getExpr()); 373 } 374 else if (If * ifstmt = dyn_cast<If>(stmt)) { 376 375 DeclareCallFunctions(ifstmt->getCondition()); 377 376 DeclareCallFunctions(ifstmt->getBody()); 378 377 } 379 else if ( const While * whl = dyn_cast<constWhile>(stmt)) {378 else if (While * whl = dyn_cast<While>(stmt)) { 380 379 DeclareCallFunctions(whl->getCondition()); 381 380 DeclareCallFunctions(whl->getBody()); … … 463 462 { 464 463 ++mCarryQueueSize; 465 DeclareCallFunctions(mstar->get Expr1());466 DeclareCallFunctions(mstar->get Expr2());464 DeclareCallFunctions(mstar->getMarker()); 465 DeclareCallFunctions(mstar->getCharClass()); 467 466 } 468 467 else if (const ScanThru * sthru = dyn_cast<const ScanThru>(expr)) … … 474 473 } 475 474 476 Value* PabloCompiler::GetMarker(const std::string & name) 477 { 475 inline Value* PabloCompiler::GetMarker(const std::string & name) { 478 476 auto itr = mMarkerMap.find(name); 479 477 if (itr == mMarkerMap.end()) { … … 484 482 } 485 483 486 void PabloCompiler::SetReturnMarker(Value * marker, const unsigned index) 487 { 484 void PabloCompiler::SetReturnMarker(Value * marker, const unsigned index) { 488 485 IRBuilder<> b(mBasicBlock); 489 486 Value* marker_bitblock = b.CreateLoad(marker); 490 Value* output_struct = b.CreateLoad(mPtr_output_addr);491 487 Value* output_indices[] = {b.getInt64(0), b.getInt32(index)}; 492 Value* output_struct_GEP = b.CreateGEP( output_struct, output_indices);488 Value* output_struct_GEP = b.CreateGEP(mOutputAddrPtr, output_indices); 493 489 b.CreateStore(marker_bitblock, output_struct_GEP); 494 490 } … … 509 505 { 510 506 Value * expr = compileExpression(assign->getExpr()); 511 Value * marker = nullptr;507 Value * marker = GetMarker(assign->getName()); 512 508 IRBuilder<> b(mBasicBlock); 513 auto f = mMarkerMap.find(assign->getName()); 514 if (f == mMarkerMap.end()) { 515 marker = b.CreateAlloca(mXi64Vect, 0, assign->getName()); 516 mMarkerMap.insert(std::make_pair(assign->getName(), marker)); 517 } 518 else { 519 marker = f->second; 520 } 521 b.CreateStore(expr, marker); 509 b.CreateStore(expr, marker)->setAlignment(BLOCK_SIZE / 8); 522 510 retVal = marker; 523 511 } … … 529 517 Value * marker = f->second; 530 518 Value * expr = compileExpression(next->getExpr()); 531 b.CreateStore(expr, marker );519 b.CreateStore(expr, marker, false)->setAlignment(BLOCK_SIZE / 8); 532 520 retVal = marker; 533 521 } … … 555 543 int if_accum_idx = mCarryQueueIdx++; 556 544 557 Value* if_carry_accum_value = genCarryInLoad(m ptr_carry_q, if_start_idx);545 Value* if_carry_accum_value = genCarryInLoad(mCarryQueuePtr, if_start_idx); 558 546 559 547 for (int c = if_start_idx+1; c < if_end_idx; c++) 560 548 { 561 Value* carryq_value = genCarryInLoad(m ptr_carry_q, c);549 Value* carryq_value = genCarryInLoad(mCarryQueuePtr, c); 562 550 if_carry_accum_value = b_ifbody.CreateOr(carryq_value, if_carry_accum_value); 563 551 } 564 genCarryOutStore(if_carry_accum_value, m ptr_carry_q, if_accum_idx);552 genCarryOutStore(if_carry_accum_value, mCarryQueuePtr, if_accum_idx); 565 553 566 554 } … … 572 560 // Have at least one internal carry. 573 561 int if_accum_idx = mCarryQueueIdx - 1; 574 Value* last_if_pending_carries = genCarryInLoad(m ptr_carry_q, if_accum_idx);562 Value* last_if_pending_carries = genCarryInLoad(mCarryQueuePtr, if_accum_idx); 575 563 if_test_value = b_entry.CreateOr(if_test_value, last_if_pending_carries); 576 564 } … … 605 593 mCarryQueueIdx = 0; 606 594 //Store the current carry queue. 607 Value* ptr_last_carry_q = m ptr_carry_q;595 Value* ptr_last_carry_q = mCarryQueuePtr; 608 596 609 597 IRBuilder<> b_wb1(mBasicBlock); … … 615 603 616 604 //Point mptr_carry_q to the new local carry queue. 617 m ptr_carry_q= ptr_while_carry_q;605 mCarryQueuePtr = ptr_while_carry_q; 618 606 619 607 returnMarker = compileStatements(whl->getBody()); … … 623 611 for (int c = 0; c < (mCarryQueueSize - idx); c++) 624 612 { 625 Value* new_carryq_value = b_wb2.CreateOr(genCarryInLoad(m ptr_carry_q, c), genCarryInLoad(ptr_last_carry_q, idx + c));613 Value* new_carryq_value = b_wb2.CreateOr(genCarryInLoad(mCarryQueuePtr, c), genCarryInLoad(ptr_last_carry_q, idx + c)); 626 614 genCarryOutStore(new_carryq_value, ptr_last_carry_q, idx + c); 627 615 } … … 630 618 631 619 mBasicBlock = whileEndBlock; 632 m ptr_carry_q= ptr_last_carry_q;620 mCarryQueuePtr = ptr_last_carry_q; 633 621 mCarryQueueIdx += idx; 634 622 … … 658 646 Value * unicode_category = b.CreateCall(ci->second, mBasisBitsAddr); 659 647 Value * ptr = b.CreateAlloca(mXi64Vect); 660 b.CreateStore(unicode_category, ptr) ;648 b.CreateStore(unicode_category, ptr)->setAlignment(BLOCK_SIZE / 8); 661 649 mi = mMarkerMap.insert(std::make_pair(call->getCallee(), ptr)).first; 662 650 } 663 retVal = b.CreateLoad(mi->second); 651 LoadInst * li = b.CreateLoad(mi->second, false, call->getCallee()); 652 li->setAlignment(BLOCK_SIZE/8); 653 retVal = li; 664 654 } 665 655 else if (const Var * var = dyn_cast<Var>(expr)) … … 667 657 auto f = mMarkerMap.find(var->getName()); 668 658 assert (f != mMarkerMap.end()); 669 retVal = b.CreateLoad(f->second, false, var->getName()); 659 LoadInst * li = b.CreateLoad(f->second, false, var->getName()); 660 li->setAlignment(BLOCK_SIZE/8); 661 retVal = li; 670 662 } 671 663 else if (const And * pablo_and = dyn_cast<And>(expr)) … … 686 678 else if (const Not * pablo_not = dyn_cast<Not>(expr)) 687 679 { 688 Value* expr_value = compileExpression(pablo_not->getExpr()); 689 retVal = b.CreateXor(expr_value, mOneInitializer, "not"); 680 retVal = genNot(compileExpression(pablo_not->getExpr())); 690 681 } 691 682 else if (const Advance * adv = dyn_cast<Advance>(expr)) … … 696 687 else if (const MatchStar * mstar = dyn_cast<MatchStar>(expr)) 697 688 { 698 Value* marker _expr = compileExpression(mstar->getExpr1());699 Value* cc _expr = compileExpression(mstar->getExpr2());700 Value* marker_and_cc = b.CreateAnd(marker _expr, cc_expr);701 retVal = b.CreateOr(b.CreateXor(genAddWithCarry(marker_and_cc, cc _expr), cc_expr), marker_expr, "matchstar");689 Value* marker = compileExpression(mstar->getMarker()); 690 Value* cc = compileExpression(mstar->getCharClass()); 691 Value* marker_and_cc = b.CreateAnd(marker, cc); 692 retVal = b.CreateOr(b.CreateXor(genAddWithCarry(marker_and_cc, cc), cc), marker, "matchstar"); 702 693 } 703 694 else if (const ScanThru * sthru = dyn_cast<ScanThru>(expr)) … … 741 732 //CarryQ - carry in. 742 733 int this_carry_idx = mCarryQueueIdx++; 743 Value* carryq_value = genCarryInLoad(m ptr_carry_q, this_carry_idx);734 Value* carryq_value = genCarryInLoad(mCarryQueuePtr, this_carry_idx); 744 735 745 736 #ifdef USE_UADD_OVERFLOW … … 770 761 Value* carry_out = genShiftHighbitToLow(b.CreateOr(carrygen, b.CreateAnd(carryprop, genNot(sum))), "carry_out"); 771 762 #endif 772 genCarryOutStore(carry_out, m ptr_carry_q, this_carry_idx);763 genCarryOutStore(carry_out, mCarryQueuePtr, this_carry_idx); 773 764 return sum; 774 765 } 775 766 776 Value* PabloCompiler::genCarryInLoad(Value* ptr_carry_q, int n) {777 IRBuilder<> b(mBasicBlock); 778 Value* carryq_idx = b.getInt64(n);779 Value* carryq_GEP = b.CreateGEP(ptr_carry_q, carryq_idx);780 return b.CreateLoad(carryq_GEP);781 } 782 783 Value* PabloCompiler::genCarryOutStore(Value* carryout, Value* ptr_carry_q, int n) {784 IRBuilder<> b(mBasicBlock); 785 Value* carryq_idx = b.getInt64(n);786 Value* carryq_GEP = b.CreateGEP(ptr_carry_q, carryq_idx);787 return b.CreateStore(carryout, carryq_GEP);788 } 789 790 Value* PabloCompiler::genBitBlockAny(Value* e) {767 LoadInst* PabloCompiler::genCarryInLoad(Value* ptr_carry_q, const unsigned index) { 768 IRBuilder<> b(mBasicBlock); 769 LoadInst * result = b.CreateLoad(b.CreateGEP(ptr_carry_q, b.getInt64(index))); 770 result->setAlignment(BLOCK_SIZE / 8); 771 return result; 772 } 773 774 StoreInst* PabloCompiler::genCarryOutStore(Value* carryout, Value* ptr_carry_q, const unsigned index ) { 775 IRBuilder<> b(mBasicBlock); 776 StoreInst * result = b.CreateStore(carryout, b.CreateGEP(ptr_carry_q, b.getInt64(index))); 777 result->setAlignment(BLOCK_SIZE / 8); 778 return result; 779 } 780 781 inline Value* PabloCompiler::genBitBlockAny(Value* e) { 791 782 IRBuilder<> b(mBasicBlock); 792 783 Value* cast_marker_value_1 = b.CreateBitCast(e, IntegerType::get(mMod->getContext(), BLOCK_SIZE)); … … 806 797 } 807 798 808 Value* PabloCompiler::genNot(Value* e, const Twine &namehint) {809 IRBuilder<> b(mBasicBlock); 810 return b.CreateXor(e , mOneInitializer, namehint);799 inline Value* PabloCompiler::genNot(Value* expr) { 800 IRBuilder<> b(mBasicBlock); 801 return b.CreateXor(expr, mOneInitializer, "not"); 811 802 } 812 803 … … 817 808 mCarryQueueIdx++; 818 809 819 Value* carryq_value = genCarryInLoad(m ptr_carry_q, this_carry_idx);810 Value* carryq_value = genCarryInLoad(mCarryQueuePtr, this_carry_idx); 820 811 821 812 Value* srli_1_value = b.CreateLShr(strm_value, 63); … … 834 825 Value* carry_out = genShiftHighbitToLow(strm_value, "carry_out"); 835 826 //CarryQ - carry out: 836 genCarryOutStore(carry_out, m ptr_carry_q, this_carry_idx);827 genCarryOutStore(carry_out, mCarryQueuePtr, this_carry_idx); 837 828 838 829 return result_value; -
icGREP/icgrep-devel/icgrep/pablo/pablo_compiler.h
r4250 r4253 87 87 PabloCompiler(const cc::CC_NameMap & nameMap, const BasisBitVars & basisBitVars, int bits); 88 88 ~PabloCompiler(); 89 LLVM_Gen_RetVal compile(const PabloBlock & cg_state);89 LLVM_Gen_RetVal compile(const PabloBlock & pb); 90 90 private: 91 91 void DefineTypes(); … … 93 93 void DeclareCallFunctions(const ExpressionList & stmts); 94 94 void DeclareCallFunctions(const PabloAST * expr); 95 void LoadBitBlocksFromStaticExtern();96 95 void SetReturnMarker(Value * marker, const unsigned index); 97 96 … … 102 101 103 102 Value* compileExpression(const PabloAST * expr); 104 Value* genCarryInLoad(Value* ptr_carry_q, int carryq_idx);105 Value* genCarryOutStore(Value* carryout, Value* ptr_carry_q, int carryq_idx);103 LoadInst* genCarryInLoad(Value* ptr_carry_q, const unsigned index); 104 StoreInst* genCarryOutStore(Value * carryout, Value * ptr_carry_q, const unsigned index); 106 105 Value* genAddWithCarry(Value* e1, Value* e2); 107 106 Value* genAdvanceWithCarry(Value* e1); … … 109 108 Value* genShiftHighbitToLow(Value* e, const Twine & namehint = ""); 110 109 Value* genShiftLeft64(Value* e, const Twine & namehint = "") ; 111 Value* genNot(Value* e , const Twine & namehint = "");110 Value* genNot(Value* expr); 112 111 113 112 #ifdef USE_UADD_OVERFLOW … … 129 128 VectorType* const mXi128Vect; 130 129 PointerType* mBasisBitsInputPtr; 131 PointerType* mOutputPtr;132 130 133 131 int mCarryQueueIdx; 134 Value* m ptr_carry_q;132 Value* mCarryQueuePtr; 135 133 136 134 int mCarryQueueSize; … … 139 137 Constant* const mOneInitializer; 140 138 141 FunctionType* mFunc Ty_0;139 FunctionType* mFunctionType; 142 140 Function* mFunc_process_block; 143 141 144 142 145 Value * mBasisBitsAddr; 146 AllocaInst* mPtr_carry_q_addr; 147 AllocaInst* mPtr_output_addr; 143 Value* mBasisBitsAddr; 144 Value* mOutputAddrPtr; 148 145 149 146 const cc::CC_NameMap & mNameMap; -
icGREP/icgrep-devel/icgrep/pablo/pe_matchstar.h
r4244 r4253 23 23 virtual ~MatchStar() { 24 24 } 25 inline PabloAST * get Expr1() const {26 return m Expr1;25 inline PabloAST * getMarker() const { 26 return mMarker; 27 27 } 28 inline PabloAST * get Expr2() const {29 return m Expr2;28 inline PabloAST * getCharClass() const { 29 return mCC; 30 30 } 31 31 protected: 32 MatchStar(PabloAST * expr1, PabloAST * expr2)32 MatchStar(PabloAST * marker, PabloAST * cc) 33 33 : PabloAST(ClassTypeId::MatchStar) 34 , m Expr1(expr1)35 , m Expr2(expr2)34 , mMarker(marker) 35 , mCC(cc) 36 36 { 37 37 38 38 } 39 39 private: 40 PabloAST * const m Expr1;41 PabloAST * const m Expr2;40 PabloAST * const mMarker; 41 PabloAST * const mCC; 42 42 }; 43 43 -
icGREP/icgrep-devel/icgrep/pablo/printer_pablos.cpp
r4252 r4253 116 116 } 117 117 else if (const MatchStar * mstar = dyn_cast<const MatchStar>(expr)) { 118 return "MatchStar (" + ShowPabloAST(mstar->get Expr1()) + ", " + ShowPabloAST(mstar->getExpr2()) + ")";118 return "MatchStar (" + ShowPabloAST(mstar->getMarker()) + ", " + ShowPabloAST(mstar->getCharClass()) + ")"; 119 119 } 120 120 else if (const ScanThru * sthru = dyn_cast<const ScanThru>(expr)) { -
icGREP/icgrep-devel/icgrep/pablo/ps_if.h
r4244 r4253 27 27 } 28 28 inline const ExpressionList & getBody() const { 29 return mPSList; 29 return mBody; 30 } 31 inline void setCarryCount(const unsigned count) { 32 mCarryCount = count; 33 } 34 inline unsigned getCarryCount() const { 35 return mCarryCount; 30 36 } 31 37 protected: 32 If(PabloAST * expr, ExpressionList && psl)38 If(PabloAST * expr, ExpressionList && body) 33 39 : PabloAST(ClassTypeId::If) 34 40 , mExpr(expr) 35 , mPSList(psl) 41 , mBody(std::move(body)) 42 , mCarryCount(0) 36 43 { 37 44 38 45 } 39 46 private: 40 PabloAST * const mExpr; 41 ExpressionList mPSList; 47 PabloAST * const mExpr; 48 ExpressionList mBody; 49 unsigned mCarryCount; 42 50 }; 43 51 -
icGREP/icgrep-devel/icgrep/pablo/ps_while.h
r4244 r4253 27 27 } 28 28 inline const ExpressionList & getBody() const { 29 return mPSList; 29 return mBody; 30 } 31 inline void setCarryCount(const unsigned count) { 32 mCarryCount = count; 33 } 34 inline unsigned getCarryCount() const { 35 return mCarryCount; 30 36 } 31 37 protected: 32 While(PabloAST * expr, ExpressionList && psl)38 While(PabloAST * expr, ExpressionList && body) 33 39 : PabloAST(ClassTypeId::While) 34 40 , mExpr(expr) 35 , mPSList(psl) 41 , mBody(std::move(body)) 42 , mCarryCount(0) 36 43 { 37 44 38 45 } 39 46 private: 40 PabloAST * const mExpr; 41 ExpressionList mPSList; 47 PabloAST * const mExpr; 48 ExpressionList mBody; 49 unsigned mCarryCount; 42 50 }; 43 51 -
icGREP/icgrep-devel/icgrep/re/re_compiler.cpp
r4252 r4253 102 102 } 103 103 else if (isa<Start>(re)) { 104 PabloAST * sol = cg.createNot(cg.createAdvance(cg.createNot(mLineFeed)));104 PabloAST * const sol = cg.createNot(cg.createAdvance(cg.createNot(mLineFeed))); 105 105 target = cg.createAssign("sol", cg.createAnd(cg.createVar(target), sol)); 106 106 } 107 107 else if (isa<End>(re)) { 108 PabloAST * eol = mLineFeed; 109 target = cg.createAssign("eol", cg.createAnd(cg.createVar(target), eol)); 108 target = cg.createAssign("eol", cg.createAnd(cg.createVar(target), mLineFeed)); 110 109 } 111 110 … … 233 232 while (ub-- != 0) { 234 233 Assign * alt = process(repeated, target, cg); 235 target = cg.createAssign(" alt", cg.createOr(cg.createVar(target), cg.createVar(alt)));234 target = cg.createAssign("m", cg.createOr(cg.createVar(target), cg.createVar(alt))); 236 235 } 237 236 return target;
Note: See TracChangeset
for help on using the changeset viewer.