diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/emit.cpp | 395 |
1 files changed, 234 insertions, 161 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 00bc2556b..c306186fb 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -761,7 +761,7 @@ struct EmitVisitor Emit("["); if(auto elementCount = declarator->elementCount) { - EmitVal(elementCount); + EmitVal(elementCount, kEOp_General); } Emit("]"); break; @@ -1047,11 +1047,11 @@ struct EmitVisitor { emitGLSLTypePrefix(matType->getElementType()); Emit("mat"); - EmitVal(matType->getRowCount()); + EmitVal(matType->getRowCount(), kEOp_General); // TODO(tfoley): only emit the next bit // for non-square matrix Emit("x"); - EmitVal(matType->getColumnCount()); + EmitVal(matType->getColumnCount(), kEOp_General); } break; @@ -1060,9 +1060,9 @@ struct EmitVisitor Emit("matrix<"); EmitType(matType->getElementType()); Emit(","); - EmitVal(matType->getRowCount()); + EmitVal(matType->getRowCount(), kEOp_General); Emit(","); - EmitVal(matType->getColumnCount()); + EmitVal(matType->getColumnCount(), kEOp_General); Emit("> "); break; @@ -1270,7 +1270,7 @@ struct EmitVisitor for(UInt ii = 0; ii < operandCount; ++ii) { if(ii != 0) emit(", "); - EmitVal(type->getOperand(ii)); + EmitVal(type->getOperand(ii), kEOp_General); } emit(" >"); } @@ -1367,7 +1367,7 @@ struct EmitVisitor // Expressions // - bool MaybeEmitParens(EOpInfo& outerPrec, EOpInfo prec) + bool maybeEmitParens(EOpInfo& outerPrec, EOpInfo prec) { bool needParens = (prec.leftPrecedence <= outerPrec.leftPrecedence) || (prec.rightPrecedence <= outerPrec.rightPrecedence); @@ -1381,6 +1381,11 @@ struct EmitVisitor return needParens; } + void maybeCloseParens(bool needClose) + { + if(needClose) Emit(")"); + } + bool isTargetIntrinsicModifierApplicable( String const& targetName) { @@ -1516,7 +1521,9 @@ struct EmitVisitor } } - void EmitVal(IRInst* val) + void EmitVal( + IRInst* val, + EOpInfo const& outerPrec) { if(auto type = as<IRType>(val)) { @@ -1524,7 +1531,7 @@ struct EmitVisitor } else { - emitIRInstExpr(context, val, IREmitMode::Default); + emitIRInstExpr(context, val, IREmitMode::Default, outerPrec); } } @@ -2288,7 +2295,7 @@ struct EmitVisitor case IRDeclaratorInfo::Flavor::Array: emitDeclarator(ctx, declarator->next); emit("["); - emitIROperand(ctx, declarator->elementCount, IREmitMode::Default); + emitIROperand(ctx, declarator->elementCount, IREmitMode::Default, kEOp_General); emit("]"); break; } @@ -2546,29 +2553,12 @@ struct EmitVisitor void emitIROperand( EmitContext* ctx, IRInst* inst, - IREmitMode mode) + IREmitMode mode, + EOpInfo const& outerPrec) { if( shouldFoldIRInstIntoUseSites(ctx, inst, mode) ) { - // HACK: Don't emit parentheses for cases that will - // wrap themsevles in `{}` to begin with. - // - // TODO: This shouldn't be needed once we are more - // systematic about not emitting redundant parentheses. - // - switch(inst->op) - { - case kIROp_makeArray: - case kIROp_makeStruct: - emitIRInstExpr(ctx, inst, mode); - break; - - default: - emit("("); - emitIRInstExpr(ctx, inst, mode); - emit(")"); - break; - } + emitIRInstExpr(ctx, inst, mode, outerPrec); return; } @@ -2593,7 +2583,7 @@ struct EmitVisitor for(UInt aa = 0; aa < argCount; ++aa) { if(aa != 0) emit(", "); - emitIROperand(ctx, args[aa].get(), mode); + emitIROperand(ctx, args[aa].get(), mode, kEOp_General); } emit(")"); } @@ -2991,8 +2981,11 @@ struct EmitVisitor IRCall* inst, IRFunc* /* func */, IRTargetIntrinsicDecoration* targetIntrinsic, - IREmitMode mode) + IREmitMode mode, + EOpInfo const& inOuterPrec) { + auto outerPrec = inOuterPrec; + IRUse* args = inst->getOperands(); UInt argCount = inst->getOperandCount(); @@ -3006,15 +2999,19 @@ struct EmitVisitor if(isOrdinaryName(name)) { // Simple case: it is just an ordinary name, so we call it like a builtin. + auto prec = kEOp_Postfix; + bool needClose = maybeEmitParens(outerPrec, prec); emit(name); Emit("("); for (UInt aa = 0; aa < argCount; ++aa) { if (aa != 0) Emit(", "); - emitIROperand(ctx, args[aa].get(), mode); + emitIROperand(ctx, args[aa].get(), mode, kEOp_General); } Emit(")"); + + maybeCloseParens(needClose); return; } else @@ -3048,7 +3045,7 @@ struct EmitVisitor UInt argIndex = d - '0'; SLANG_RELEASE_ASSERT((0 <= argIndex) && (argIndex < argCount)); Emit("("); - emitIROperand(ctx, args[argIndex].get(), mode); + emitIROperand(ctx, args[argIndex].get(), mode, kEOp_General); Emit(")"); } break; @@ -3076,9 +3073,9 @@ struct EmitVisitor } Emit("("); - emitIROperand(ctx, textureArg, mode); + emitIROperand(ctx, textureArg, mode, kEOp_General); Emit(","); - emitIROperand(ctx, samplerArg, mode); + emitIROperand(ctx, samplerArg, mode, kEOp_General); Emit(")"); } else @@ -3173,7 +3170,7 @@ struct EmitVisitor { // In the simple case, the operand is already a 4-vector, // so we can just emit it as-is. - emitIROperand(ctx, arg, mode); + emitIROperand(ctx, arg, mode, kEOp_General); } else { @@ -3183,7 +3180,7 @@ struct EmitVisitor // emitVectorTypeName(elementType, 4); Emit("("); - emitIROperand(ctx, arg, mode); + emitIROperand(ctx, arg, mode, kEOp_General); for(IRIntegerValue ii = elementCount; ii < 4; ++ii) { Emit(", "); @@ -3253,22 +3250,22 @@ struct EmitVisitor // to be broken out into its own argument. // Emit("("); - emitIROperand(ctx, arg->getOperand(0), mode); + emitIROperand(ctx, arg->getOperand(0), mode, kEOp_General); Emit("), ("); - emitIROperand(ctx, arg->getOperand(1), mode); + emitIROperand(ctx, arg->getOperand(1), mode, kEOp_General); Emit(")"); } else { Emit("("); - emitIROperand(ctx, arg, mode); + emitIROperand(ctx, arg, mode, kEOp_General); Emit(")"); } } else { Emit("("); - emitIROperand(ctx, arg, mode); + emitIROperand(ctx, arg, mode, kEOp_General); Emit(")"); } } @@ -3339,8 +3336,12 @@ struct EmitVisitor EmitContext* ctx, IRCall* inst, IRFunc* func, - IREmitMode mode) + IREmitMode mode, + EOpInfo const& inOuterPrec) { + auto outerPrec = inOuterPrec; + bool needClose = false; + // For a call with N arguments, the instruction will // have N+1 operands. We will start consuming operands // starting at the index 1. @@ -3357,7 +3358,8 @@ struct EmitVisitor inst, func, targetIntrinsicDecoration, - mode); + mode, + outerPrec); return; } @@ -3406,20 +3408,28 @@ struct EmitVisitor if(name == "operator[]") { // The user is invoking a built-in subscript operator - emit("("); - emitIROperand(ctx, inst->getOperand(operandIndex++), mode); - emit(")["); - emitIROperand(ctx, inst->getOperand(operandIndex++), mode); + + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, inst->getOperand(operandIndex++), mode, leftSide(outerPrec, prec)); + emit("["); + emitIROperand(ctx, inst->getOperand(operandIndex++), mode, kEOp_General); emit("]"); if(operandIndex < operandCount) { emit(" = "); - emitIROperand(ctx, inst->getOperand(operandIndex++), mode); + emitIROperand(ctx, inst->getOperand(operandIndex++), mode, kEOp_General); } + + maybeCloseParens(needClose); return; } + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); + // The mangled function name currently records // the number of explicit parameters, and thus // doesn't include the implicit `this` parameter. @@ -3430,10 +3440,8 @@ struct EmitVisitor if(argCount != paramCount) { // Looks like a member function call - emit("("); - emitIROperand(ctx, inst->getOperand(operandIndex), mode); - emit(")."); - + emitIROperand(ctx, inst->getOperand(operandIndex), mode, leftSide(outerPrec, prec)); + emit("."); operandIndex++; } @@ -3443,43 +3451,54 @@ struct EmitVisitor for(; operandIndex < operandCount; ++operandIndex ) { if(!first) emit(", "); - emitIROperand(ctx, inst->getOperand(operandIndex), mode); + emitIROperand(ctx, inst->getOperand(operandIndex), mode, kEOp_General); first = false; } emit(")"); + + maybeCloseParens(needClose); } void emitIRCallExpr( EmitContext* ctx, IRCall* inst, - IREmitMode mode) + IREmitMode mode, + EOpInfo outerPrec) { // We want to detect any call to an intrinsic operation, // that we can emit it directly without mangling, etc. auto funcValue = inst->getOperand(0); if(auto irFunc = asTargetIntrinsic(ctx, funcValue)) { - emitIntrinsicCallExpr(ctx, inst, irFunc, mode); + emitIntrinsicCallExpr(ctx, inst, irFunc, mode, outerPrec); } else { - emitIROperand(ctx, funcValue, mode); + auto prec = kEOp_Postfix; + bool needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, funcValue, mode, leftSide(outerPrec, prec)); emit("("); UInt argCount = inst->getOperandCount(); for( UInt aa = 1; aa < argCount; ++aa ) { if(aa != 1) emit(", "); - emitIROperand(ctx, inst->getOperand(aa), mode); + emitIROperand(ctx, inst->getOperand(aa), mode, kEOp_General); } emit(")"); + + maybeCloseParens(needClose); } } void emitIRInstExpr( EmitContext* ctx, IRInst* inst, - IREmitMode mode) + IREmitMode mode, + EOpInfo const& inOuterPrec) { + EOpInfo outerPrec = inOuterPrec; + bool needClose = false; switch(inst->op) { case kIROp_IntLit: @@ -3494,11 +3513,14 @@ struct EmitVisitor // Simple constructor call if( inst->getOperandCount() == 1 && getTarget(ctx) == CodeGenTarget::HLSL) { + auto prec = kEOp_Prefix; + needClose = maybeEmitParens(outerPrec, prec); + // Need to emit as cast for HLSL emit("("); emitIRType(ctx, inst->getDataType()); emit(") "); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, rightSide(outerPrec,prec)); } else { @@ -3508,6 +3530,7 @@ struct EmitVisitor break; case kIROp_constructVectorFromScalar: + // Simple constructor call if( getTarget(ctx) == CodeGenTarget::HLSL ) { @@ -3520,7 +3543,7 @@ struct EmitVisitor emitIRType(ctx, inst->getDataType()); } emit("("); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, kEOp_General); emit(")"); break; @@ -3532,7 +3555,10 @@ struct EmitVisitor if (!isDerefBaseImplicit(ctx, fieldExtract->getBase())) { - emitIROperand(ctx, fieldExtract->getBase(), mode); + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, fieldExtract->getBase(), mode, leftSide(outerPrec, prec)); emit("."); } emit(getIRName(fieldExtract->getField())); @@ -3547,7 +3573,10 @@ struct EmitVisitor if (!isDerefBaseImplicit(ctx, ii->getBase())) { - emitIROperand(ctx, ii->getBase(), mode); + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, ii->getBase(), mode, leftSide(outerPrec, prec)); emit("."); } @@ -3555,36 +3584,37 @@ struct EmitVisitor } break; -#define CASE(OPCODE, OP) \ - case OPCODE: \ - emitIROperand(ctx, inst->getOperand(0), mode); \ - emit(" " #OP " "); \ - emitIROperand(ctx, inst->getOperand(1), mode); \ +#define CASE(OPCODE, PREC, OP) \ + case OPCODE: \ + needClose = maybeEmitParens(outerPrec, kEOp_##PREC); \ + emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrec, kEOp_##PREC)); \ + emit(" " #OP " "); \ + emitIROperand(ctx, inst->getOperand(1), mode, rightSide(outerPrec, kEOp_##PREC)); \ break - CASE(kIROp_Add, +); - CASE(kIROp_Sub, -); - CASE(kIROp_Div, /); - CASE(kIROp_Mod, %); + CASE(kIROp_Add, Add, +); + CASE(kIROp_Sub, Sub, -); + CASE(kIROp_Div, Div, /); + CASE(kIROp_Mod, Mod, %); - CASE(kIROp_Lsh, <<); - CASE(kIROp_Rsh, >>); + CASE(kIROp_Lsh, Lsh, <<); + CASE(kIROp_Rsh, Rsh, >>); // TODO: Need to pull out component-wise // comparison cases for matrices/vectors - CASE(kIROp_Eql, ==); - CASE(kIROp_Neq, !=); - CASE(kIROp_Greater, >); - CASE(kIROp_Less, <); - CASE(kIROp_Geq, >=); - CASE(kIROp_Leq, <=); + CASE(kIROp_Eql, Eql, ==); + CASE(kIROp_Neq, Neq, !=); + CASE(kIROp_Greater, Greater, >); + CASE(kIROp_Less, Less, <); + CASE(kIROp_Geq, Geq, >=); + CASE(kIROp_Leq, Leq, <=); - CASE(kIROp_BitAnd, &); - CASE(kIROp_BitXor, ^); - CASE(kIROp_BitOr, |); + CASE(kIROp_BitAnd, BitAnd, &); + CASE(kIROp_BitXor, BitXor, ^); + CASE(kIROp_BitOr, BitOr, |); - CASE(kIROp_And, &&); - CASE(kIROp_Or, ||); + CASE(kIROp_And, And, &&); + CASE(kIROp_Or, Or, ||); #undef CASE @@ -3598,36 +3628,47 @@ struct EmitVisitor && as<IRMatrixType>(inst->getOperand(1)->getDataType())) { emit("matrixCompMult("); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, kEOp_General); emit(", "); - emitIROperand(ctx, inst->getOperand(1), mode); + emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); emit(")"); } else { // Default handling is to just rely on infix // `operator*`. - emitIROperand(ctx, inst->getOperand(0), mode); + auto prec = kEOp_Mul; + needClose = maybeEmitParens(outerPrec, prec); + emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrec, prec)); emit(" * "); - emitIROperand(ctx, inst->getOperand(1), mode); + emitIROperand(ctx, inst->getOperand(1), mode, rightSide(prec, outerPrec)); } break; case kIROp_Not: { + auto prec = kEOp_Prefix; + needClose = maybeEmitParens(outerPrec, prec); + emit("!"); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, rightSide(prec, outerPrec)); } break; case kIROp_Neg: { + auto prec = kEOp_Prefix; + needClose = maybeEmitParens(outerPrec, prec); + emit("-"); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, rightSide(prec, outerPrec)); } break; case kIROp_BitNot: { + auto prec = kEOp_Prefix; + needClose = maybeEmitParens(outerPrec, prec); + if (as<IRBoolType>(inst->getDataType())) { emit("!"); @@ -3636,64 +3677,62 @@ struct EmitVisitor { emit("~"); } - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, rightSide(prec, outerPrec)); } break; - case kIROp_Sample: - emitIROperand(ctx, inst->getOperand(0), mode); - emit(".Sample("); - emitIROperand(ctx, inst->getOperand(1), mode); - emit(", "); - emitIROperand(ctx, inst->getOperand(2), mode); - emit(")"); - break; - - case kIROp_SampleGrad: - // argument 0 is the instruction's type - emitIROperand(ctx, inst->getOperand(0), mode); - emit(".SampleGrad("); - emitIROperand(ctx, inst->getOperand(1), mode); - emit(", "); - emitIROperand(ctx, inst->getOperand(2), mode); - emit(", "); - emitIROperand(ctx, inst->getOperand(3), mode); - emit(", "); - emitIROperand(ctx, inst->getOperand(4), mode); - emit(")"); - break; case kIROp_Load: - // TODO: this logic will really only work for a simple variable reference... - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, outerPrec); break; case kIROp_Store: - // TODO: this logic will really only work for a simple variable reference... - emitIROperand(ctx, inst->getOperand(0), mode); - emit(" = "); - emitIROperand(ctx, inst->getOperand(1), mode); + { + auto prec = kEOp_Assign; + needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrec, prec)); + emit(" = "); + emitIROperand(ctx, inst->getOperand(1), mode, rightSide(prec, outerPrec)); + } break; case kIROp_Call: { - emitIRCallExpr(ctx, (IRCall*)inst, mode); + emitIRCallExpr(ctx, (IRCall*)inst, mode, outerPrec); } break; case kIROp_BufferLoad: case kIROp_BufferElementRef: - emitIROperand(ctx, inst->getOperand(0), mode); - emit("["); - emitIROperand(ctx, inst->getOperand(1), mode); - emit("]"); + { + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrec, prec)); + emit("["); + emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); + emit("]"); + } break; case kIROp_BufferStore: - emitIROperand(ctx, inst->getOperand(0), mode); - emit("["); - emitIROperand(ctx, inst->getOperand(1), mode); - emit("] = "); - emitIROperand(ctx, inst->getOperand(2), mode); + { + auto precAssign = kEOp_Assign; + needClose = maybeEmitParens(outerPrec, precAssign); + + auto outerPrecSubscript = precAssign; + auto precSubscript = kEOp_Postfix; + bool needCloseSubscript = maybeEmitParens(outerPrecSubscript, precSubscript); + + emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrecSubscript, precSubscript)); + emit("["); + emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); + emit("]"); + maybeCloseParens(needCloseSubscript); + + emit(" = "); + emitIROperand(ctx, inst->getOperand(2), mode, rightSide(outerPrec, precAssign)); + } break; case kIROp_GroupMemoryBarrierWithGroupSync: @@ -3706,18 +3745,26 @@ struct EmitVisitor // HACK: deal with translation of GLSL geometry shader input arrays. if(auto decoration = inst->getOperand(0)->findDecoration<IRGLSLOuterArrayDecoration>()) { + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); + emit(decoration->outerArrayName); emit("["); - emitIROperand(ctx, inst->getOperand(1), mode); + emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); emit("]."); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, rightSide(prec, outerPrec)); break; } + else + { + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); - emitIROperand(ctx, inst->getOperand(0), mode); - emit("["); - emitIROperand(ctx, inst->getOperand(1), mode); - emit("]"); + emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrec, prec)); + emit("["); + emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); + emit("]"); + } break; case kIROp_Mul_Vector_Matrix: @@ -3733,24 +3780,30 @@ struct EmitVisitor // because the notion of what is a "row" vs. a "column" // is reversed between HLSL/Slang and GLSL. // - emitIROperand(ctx, inst->getOperand(1), mode); + auto prec = kEOp_Mul; + needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, inst->getOperand(1), mode, leftSide(outerPrec, prec)); emit(" * "); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, rightSide(prec, outerPrec)); } else { emit("mul("); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, kEOp_General); emit(", "); - emitIROperand(ctx, inst->getOperand(1), mode); + emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); emit(")"); } break; case kIROp_swizzle: { + auto prec = kEOp_Postfix; + needClose = maybeEmitParens(outerPrec, prec); + auto ii = (IRSwizzle*)inst; - emitIROperand(ctx, ii->getBase(), mode); + emitIROperand(ctx, ii->getBase(), mode, leftSide(outerPrec, prec)); emit("."); UInt elementCount = ii->getElementCount(); for (UInt ee = 0; ee < elementCount; ++ee) @@ -3770,17 +3823,20 @@ struct EmitVisitor case kIROp_Specialize: { - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, outerPrec); } break; case kIROp_Select: { - emitIROperand(ctx, inst->getOperand(0), mode); + auto prec = kEOp_Conditional; + needClose = maybeEmitParens(outerPrec, prec); + + emitIROperand(ctx, inst->getOperand(0), mode, leftSide(outerPrec, prec)); emit(" ? "); - emitIROperand(ctx, inst->getOperand(1), mode); + emitIROperand(ctx, inst->getOperand(1), mode, prec); emit(" : "); - emitIROperand(ctx, inst->getOperand(2), mode); + emitIROperand(ctx, inst->getOperand(2), mode, rightSide(prec, outerPrec)); } break; @@ -3800,7 +3856,7 @@ struct EmitVisitor for (UInt aa = 0; aa < argCount; ++aa) { if (aa != 0) emit(", "); - emitIROperand(ctx, inst->getOperand(aa), mode); + emitIROperand(ctx, inst->getOperand(aa), mode, kEOp_General); } emit(" }"); } @@ -3810,6 +3866,7 @@ struct EmitVisitor emit("/* unhandled */"); break; } + maybeCloseParens(needClose); } void emitIRInst( @@ -3847,7 +3904,7 @@ struct EmitVisitor { default: emitIRInstResultDecl(ctx, inst); - emitIRInstExpr(ctx, inst, mode); + emitIRInstExpr(ctx, inst, mode, kEOp_General); emit(";\n"); break; @@ -3892,7 +3949,7 @@ struct EmitVisitor case kIROp_ReturnVal: emit("return "); - emitIROperand(ctx, ((IRReturnVal*) inst)->getVal(), mode); + emitIROperand(ctx, ((IRReturnVal*) inst)->getVal(), mode, kEOp_General); emit(";\n"); break; @@ -3904,9 +3961,14 @@ struct EmitVisitor { auto ii = (IRSwizzleSet*)inst; emitIRInstResultDecl(ctx, inst); - emitIROperand(ctx, inst->getOperand(0), mode); + emitIROperand(ctx, inst->getOperand(0), mode, kEOp_General); emit(";\n"); - emitIROperand(ctx, inst, mode); + + auto subscriptOuter = kEOp_General; + auto subscriptPrec = kEOp_Postfix; + bool needCloseSubscript = maybeEmitParens(subscriptOuter, subscriptPrec); + + emitIROperand(ctx, inst, mode, leftSide(subscriptOuter, subscriptPrec)); emit("."); UInt elementCount = ii->getElementCount(); for (UInt ee = 0; ee < elementCount; ++ee) @@ -3921,18 +3983,24 @@ struct EmitVisitor char const* kComponents[] = { "x", "y", "z", "w" }; emit(kComponents[elementIndex]); } + maybeCloseParens(needCloseSubscript); + emit(" = "); - emitIROperand(ctx, inst->getOperand(1), mode); + emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General); emit(";\n"); } break; case kIROp_SwizzledStore: { + auto subscriptOuter = kEOp_General; + auto subscriptPrec = kEOp_Postfix; + bool needCloseSubscript = maybeEmitParens(subscriptOuter, subscriptPrec); + + auto ii = cast<IRSwizzledStore>(inst); - emit("("); - emitIROperand(ctx, ii->getDest(), mode); - emit(")."); + emitIROperand(ctx, ii->getDest(), mode, leftSide(subscriptOuter, subscriptPrec)); + emit("."); UInt elementCount = ii->getElementCount(); for (UInt ee = 0; ee < elementCount; ++ee) { @@ -3946,8 +4014,10 @@ struct EmitVisitor char const* kComponents[] = { "x", "y", "z", "w" }; emit(kComponents[elementIndex]); } + maybeCloseParens(needCloseSubscript); + emit(" = "); - emitIROperand(ctx, ii->getSource(), mode); + emitIROperand(ctx, ii->getSource(), mode, kEOp_General); emit(";\n"); } break; @@ -4054,9 +4124,12 @@ struct EmitVisitor IRInst* arg = args[argIndex].get(); - emitIROperand(ctx, pp, IREmitMode::Default); + auto outerPrec = kEOp_General; + auto prec = kEOp_Assign; + + emitIROperand(ctx, pp, IREmitMode::Default, leftSide(outerPrec, prec)); emit(" = "); - emitIROperand(ctx, arg, IREmitMode::Default); + emitIROperand(ctx, arg, IREmitMode::Default, rightSide(prec, outerPrec)); emit(";\n"); } } @@ -4187,7 +4260,7 @@ struct EmitVisitor // instead of the current `if(condition) {} else { elseRegion }` emit("if("); - emitIROperand(ctx, ifRegion->condition, IREmitMode::Default); + emitIROperand(ctx, ifRegion->condition, IREmitMode::Default, kEOp_General); emit(")\n{\n"); indent(); emitRegion(ctx, ifRegion->thenRegion); @@ -4261,7 +4334,7 @@ struct EmitVisitor // Emit the start of our statement. emit("switch("); - emitIROperand(ctx, switchRegion->condition, IREmitMode::Default); + emitIROperand(ctx, switchRegion->condition, IREmitMode::Default, kEOp_General); emit(")\n{\n"); auto defaultCase = switchRegion->defaultCase; @@ -4270,7 +4343,7 @@ struct EmitVisitor for(auto caseVal : currentCase->values) { emit("case "); - emitIROperand(ctx, caseVal, IREmitMode::Default); + emitIROperand(ctx, caseVal, IREmitMode::Default, kEOp_General); emit(":\n"); } if(currentCase.Ptr() == defaultCase) @@ -5921,7 +5994,7 @@ struct EmitVisitor // cases where the value might *need* to emit as a named referenced // (e.g., when it names another constant directly). // - emitIROperand(ctx, returnInst->getVal(), IREmitMode::GlobalConstant); + emitIROperand(ctx, returnInst->getVal(), IREmitMode::GlobalConstant, kEOp_General); } void emitIRGlobalConstant( |
