/// <summary> /// Creates an invocation block from a callee and an argument list. /// </summary> /// <param name="CodeGenerator">The code generator that creates this block.</param> /// <param name="Callee">The delegate to call.</param> /// <param name="Arguments">The argument list for the call.</param> /// <param name="CanThrow">Tells if the invocation can throw an exception.</param> public InvocationBlock( ICodeGenerator CodeGenerator, CodeBlock Callee, IEnumerable <CodeBlock> Arguments, bool CanThrow) { this.codeGen = CodeGenerator; this.Callee = Callee; this.Arguments = Arguments; this.methodSignature = MethodType.GetMethod(Callee.Type); this.retType = methodSignature.ReturnType; this.CanThrow = CanThrow; }
/// <inheritdoc/> public override CodeBlock EmitThrow(LLVMCodeGenerator CodeGenerator, CodeBlock Exception) { // Generate something more or less like this: // // %1 = call i8* @__cxa_allocate_exception(i64 <sizeof(value-to-throw)>) // %2 = bitcast i8* %1 to <typeof(value-to-throw)>* // store i8* <value-to-throw>, <typeof(value-to-throw)>* %2 // call void @__cxa_throw(i8* %1, i8* bitcast (i8** @_ZTIPv to i8*), i8* null) // unreachable // var exceptionType = Exception.Type; var exceptionStorageSpec = new DescribedVariableMember( "exception_storage", PrimitiveTypes.Void.MakePointerType(PointerKind.TransientPointer)); var exceptionStorage = CodeGenerator.DeclareLocal( new UniqueTag(exceptionStorageSpec.Name.ToString()), exceptionStorageSpec); var allocStmt = exceptionStorage.EmitSet( new InvocationBlock( CodeGenerator, new IntrinsicBlock(CodeGenerator, IntrinsicValue.CxaAllocateException), new CodeBlock[] { (CodeBlock)CodeGenerator.EmitTypeBinary( CodeGenerator.EmitSizeOf(exceptionType), MethodType .GetMethod(IntrinsicValue.CxaAllocateException.Type) .GetParameters()[0].ParameterType, Operator.StaticCast) }, false)); var storeStmt = CodeGenerator.EmitStoreAtAddress( CodeGenerator.EmitTypeBinary( exceptionStorage.EmitGet(), exceptionType.MakePointerType(PointerKind.TransientPointer), Operator.ReinterpretCast), Exception); var throwStmt = new InvocationBlock( CodeGenerator, new IntrinsicBlock(CodeGenerator, IntrinsicValue.CxaThrow), new CodeBlock[] { (CodeBlock)exceptionStorage.EmitGet(), (CodeBlock)CodeGenerator.EmitTypeBinary( new IntrinsicBlock(CodeGenerator, IntrinsicValue.CxaVoidPointerRtti), PrimitiveTypes.Void.MakePointerType(PointerKind.TransientPointer), Operator.ReinterpretCast), (CodeBlock)CodeGenerator.EmitTypeBinary( CodeGenerator.EmitNull(), PrimitiveTypes.Void.MakePointerType(PointerKind.TransientPointer), Operator.ReinterpretCast) }, true); return((CodeBlock)CodeGenerator.EmitSequence( allocStmt, CodeGenerator.EmitSequence( storeStmt, CodeGenerator.EmitSequence( throwStmt, new UnreachableBlock(CodeGenerator, PrimitiveTypes.Void))))); }