|
13 | 13 | static const instruction INS_I_const = INS_i64_const; |
14 | 14 | static const instruction INS_I_add = INS_i64_add; |
15 | 15 | static const instruction INS_I_sub = INS_i64_sub; |
| 16 | +static const instruction INS_I_le_u = INS_i64_le_u; |
| 17 | +static const instruction INS_I_gt_u = INS_i64_gt_u; |
16 | 18 | #else // !TARGET_64BIT |
17 | 19 | static const instruction INS_I_const = INS_i32_const; |
18 | 20 | static const instruction INS_I_add = INS_i32_add; |
19 | 21 | static const instruction INS_I_sub = INS_i32_sub; |
| 22 | +static const instruction INS_I_le_u = INS_i32_le_u; |
| 23 | +static const instruction INS_I_gt_u = INS_i32_gt_u; |
20 | 24 | #endif // !TARGET_64BIT |
21 | 25 |
|
22 | 26 | void CodeGen::genMarkLabelsForCodegen() |
@@ -495,6 +499,10 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) |
495 | 499 | genCodeForNegNot(treeNode->AsOp()); |
496 | 500 | break; |
497 | 501 |
|
| 502 | + case GT_NULLCHECK: |
| 503 | + genCodeForNullCheck(treeNode->AsIndir()); |
| 504 | + break; |
| 505 | + |
498 | 506 | case GT_IND: |
499 | 507 | genCodeForIndir(treeNode->AsIndir()); |
500 | 508 | break; |
@@ -922,6 +930,37 @@ void CodeGen::genCodeForDivMod(GenTreeOp* treeNode) |
922 | 930 | { |
923 | 931 | genConsumeOperands(treeNode); |
924 | 932 |
|
| 933 | + // wasm stack is |
| 934 | + // divisor (top) |
| 935 | + // dividend (next) |
| 936 | + // ... |
| 937 | + // TODO-WASM: To check for exception, we will have to spill these to |
| 938 | + // internal registers along the way, like so: |
| 939 | + // |
| 940 | + // ... push dividend |
| 941 | + // tee.local $temp1 |
| 942 | + // ... push divisor |
| 943 | + // tee.local $temp2 |
| 944 | + // ... exception checks (using $temp1 and $temp2; will introduce flow) |
| 945 | + // div/mod op |
| 946 | + |
| 947 | + if (!varTypeIsFloating(treeNode->TypeGet())) |
| 948 | + { |
| 949 | + ExceptionSetFlags exSetFlags = treeNode->OperExceptions(compiler); |
| 950 | + |
| 951 | + // TODO-WASM:(AnyVal / 0) => DivideByZeroException |
| 952 | + // |
| 953 | + if ((exSetFlags & ExceptionSetFlags::DivideByZeroException) != ExceptionSetFlags::None) |
| 954 | + { |
| 955 | + } |
| 956 | + |
| 957 | + // TODO-WASM: (MinInt / -1) => ArithmeticException |
| 958 | + // |
| 959 | + if ((exSetFlags & ExceptionSetFlags::ArithmeticException) != ExceptionSetFlags::None) |
| 960 | + { |
| 961 | + } |
| 962 | + } |
| 963 | + |
925 | 964 | instruction ins; |
926 | 965 | switch (PackOperAndType(treeNode->OperGet(), treeNode->TypeGet())) |
927 | 966 | { |
@@ -1136,6 +1175,48 @@ void CodeGen::genCodeForNegNot(GenTreeOp* tree) |
1136 | 1175 | genProduceReg(tree); |
1137 | 1176 | } |
1138 | 1177 |
|
| 1178 | +//--------------------------------------------------------------------- |
| 1179 | +// genCodeForNullCheck - generate code for a GT_NULLCHECK node |
| 1180 | +// |
| 1181 | +// Arguments: |
| 1182 | +// tree - the GT_NULLCHECK node |
| 1183 | +// |
| 1184 | +// Notes: |
| 1185 | +// If throw helper calls are being emitted inline, we need |
| 1186 | +// to wrap the resulting codegen in a block/end pair. |
| 1187 | +// |
| 1188 | +void CodeGen::genCodeForNullCheck(GenTreeIndir* tree) |
| 1189 | +{ |
| 1190 | + genConsumeAddress(tree->Addr()); |
| 1191 | + |
| 1192 | + // TODO-WASM: refactor once we have implemented other cases invoking throw helpers |
| 1193 | + if (compiler->fgUseThrowHelperBlocks()) |
| 1194 | + { |
| 1195 | + Compiler::AddCodeDsc* const add = compiler->fgFindExcptnTarget(SCK_NULL_CHECK, compiler->compCurBB); |
| 1196 | + |
| 1197 | + if (add == nullptr) |
| 1198 | + { |
| 1199 | + NYI_WASM("Missing null check demand"); |
| 1200 | + } |
| 1201 | + |
| 1202 | + assert(add != nullptr); |
| 1203 | + assert(add->acdUsed); |
| 1204 | + GetEmitter()->emitIns_I(INS_I_const, EA_PTRSIZE, compiler->compMaxUncheckedOffsetForNullObject); |
| 1205 | + GetEmitter()->emitIns(INS_I_le_u); |
| 1206 | + inst_JMP(EJ_jmpif, add->acdDstBlk); |
| 1207 | + } |
| 1208 | + else |
| 1209 | + { |
| 1210 | + GetEmitter()->emitIns_I(INS_I_const, EA_PTRSIZE, compiler->compMaxUncheckedOffsetForNullObject); |
| 1211 | + GetEmitter()->emitIns(INS_I_le_u); |
| 1212 | + GetEmitter()->emitIns(INS_if); |
| 1213 | + // TODO-WASM: codegen for the call instead of unreachable |
| 1214 | + // genEmitHelperCall(compiler->acdHelper(SCK_NULL_CHECK), 0, EA_UNKNOWN); |
| 1215 | + GetEmitter()->emitIns(INS_unreachable); |
| 1216 | + GetEmitter()->emitIns(INS_end); |
| 1217 | + } |
| 1218 | +} |
| 1219 | + |
1139 | 1220 | //------------------------------------------------------------------------ |
1140 | 1221 | // genCodeForLclAddr: Generates the code for GT_LCL_ADDR. |
1141 | 1222 | // |
|
0 commit comments