Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/typescript-parity-report.md

Large diffs are not rendered by default.

694 changes: 694 additions & 0 deletions internal/backend/llvm/crypto.go

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions internal/backend/llvm/emit.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,45 @@ func EmitWithOptions(module ir.Module, options Options) (string, error) {
out.WriteString("declare i32 @scriptgo_crypto_pbkdf2_sync(ptr, ptr, double, double, ptr, ptr)\n\n")
out.WriteString("declare i32 @scriptgo_crypto_hkdf_sync(ptr, ptr, ptr, ptr, double, ptr)\n\n")
out.WriteString("declare i32 @scriptgo_crypto_scrypt_sync(ptr, ptr, double, ptr)\n\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_create(ptr, ptr, ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_update(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_final(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_set_aad(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_get_tag(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_set_tag(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_set_auto_padding(ptr, double)\n")
out.WriteString("declare i32 @scriptgo_crypto_cipher_destroy(ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_get_cipher_info(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_sign(ptr, ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_verify(ptr, ptr, ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_public_encrypt(ptr, ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_public_decrypt(ptr, ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_private_encrypt(ptr, ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_private_decrypt(ptr, ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_generate_key_pair_sync(ptr, double, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_key_details(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_dh_create(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_dh_create_group(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_dh_generate_keys(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_dh_compute_secret(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_dh_get_key(ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_dh_set_key(ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_dh_destroy(ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_ecdh_create(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_ecdh_generate_keys(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_ecdh_compute_secret(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_ecdh_get_key(ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_ecdh_set_key(ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_ecdh_destroy(ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_spkac_verify(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_spkac_export_challenge(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_spkac_export_public_key(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_x509_check_private_key(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_x509_verify(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_get_fips(ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_set_fips(double)\n")
out.WriteString("declare i32 @scriptgo_crypto_secure_heap_used(ptr)\n")
out.WriteString("declare i32 @scriptgo_crypto_set_engine(ptr, double)\n\n")
out.WriteString("declare i32 @scriptgo_zlib_transform_string(ptr, double, ptr)\n")
out.WriteString("declare i32 @scriptgo_zlib_transform_buffer(ptr, double, ptr)\n\n")
out.WriteString("declare i32 @scriptgo_date_now(ptr)\n")
Expand Down
185 changes: 0 additions & 185 deletions internal/backend/llvm/sys.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,191 +619,6 @@ func (e *functionEmitter) emitProcessIntrinsic(out *strings.Builder, instruction
}
}

func (e *functionEmitter) emitCryptoIntrinsic(out *strings.Builder, instruction ir.Instruction) error {
switch instruction.Callee {
case "__crypto.randomUUID":
if len(instruction.Args) != 0 || instruction.Type != ir.TypeString {
return fmt.Errorf("crypto.randomUUID has invalid signature")
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_random_uuid(ptr %%%s)\n", status, slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.hashDigest":
if len(instruction.Args) < 2 || len(instruction.Args) > 3 || instruction.Type != ir.TypeString {
return fmt.Errorf("crypto.hashDigest has invalid signature")
}
encodingArg := "null"
if len(instruction.Args) == 3 {
encodingArg = fmt.Sprintf("%%%s", instruction.Args[2])
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_hash_digest(ptr %%%s, ptr %%%s, ptr %s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], encodingArg, slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.hashDigestBuffer":
if len(instruction.Args) < 2 || len(instruction.Args) > 3 || instruction.Type != ir.TypeString {
return fmt.Errorf("crypto.hashDigestBuffer has invalid signature")
}
encodingArg := "null"
if len(instruction.Args) == 3 {
encodingArg = fmt.Sprintf("%%%s", instruction.Args[2])
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_hash_digest_buffer(ptr %%%s, ptr %%%s, ptr %s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], encodingArg, slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.randomBytes":
if len(instruction.Args) != 1 || instruction.Type != ir.TypeBuffer {
return fmt.Errorf("crypto.randomBytes has invalid signature")
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_random_bytes(double %%%s, ptr %%%s)\n", status, instruction.Args[0], slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.randomInt":
if len(instruction.Args) != 2 || instruction.Type != ir.TypeNumber {
return fmt.Errorf("crypto.randomInt has invalid signature")
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca double\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_random_int(double %%%s, double %%%s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load double, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.randomFill":
if len(instruction.Args) < 1 || len(instruction.Args) > 4 {
return fmt.Errorf("crypto.randomFill has invalid signature")
}
offArg := "0.0"
szArg := "0.0"
if len(instruction.Args) >= 2 {
offArg = fmt.Sprintf("%%%s", instruction.Args[1])
}
if len(instruction.Args) >= 3 {
szArg = fmt.Sprintf("%%%s", instruction.Args[2])
}
callback := "null"
if len(instruction.Args) == 4 {
callback = fmt.Sprintf("%%%s", instruction.Args[3])
}
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_random_fill(ptr %%%s, double %s, double %s, ptr %s)\n", status, instruction.Args[0], offArg, szArg, callback)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
if instruction.Type == ir.TypeBuffer {
fmt.Fprintf(out, " %%%s = bitcast ptr %%%s to ptr\n", instruction.Result, instruction.Args[0])
}
return nil
case "__crypto.timingSafeEqual":
if len(instruction.Args) != 2 || instruction.Type != ir.TypeBool {
return fmt.Errorf("crypto.timingSafeEqual has invalid signature")
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca double\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_timing_safe_equal(ptr %%%s, ptr %%%s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s.f64 = load double, ptr %%%s\n", instruction.Result, slot)
fmt.Fprintf(out, " %%%s = fcmp one double %%%s.f64, 0.0\n", instruction.Result, instruction.Result)
return nil
case "__crypto.hmacDigest":
if len(instruction.Args) < 3 || len(instruction.Args) > 4 || instruction.Type != ir.TypeString {
return fmt.Errorf("crypto.hmacDigest has invalid signature")
}
encodingArg := "null"
if len(instruction.Args) == 4 {
encodingArg = fmt.Sprintf("%%%s", instruction.Args[3])
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_hmac_digest(ptr %%%s, ptr %%%s, ptr %%%s, ptr %s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], instruction.Args[2], encodingArg, slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.hmacDigestBuffer":
if len(instruction.Args) < 3 || len(instruction.Args) > 4 || instruction.Type != ir.TypeString {
return fmt.Errorf("crypto.hmacDigestBuffer has invalid signature")
}
encodingArg := "null"
if len(instruction.Args) == 4 {
encodingArg = fmt.Sprintf("%%%s", instruction.Args[3])
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_hmac_digest_buffer(ptr %%%s, ptr %%%s, ptr %%%s, ptr %s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], instruction.Args[2], encodingArg, slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.pbkdf2Sync":
if len(instruction.Args) < 4 || len(instruction.Args) > 5 || instruction.Type != ir.TypeBuffer {
return fmt.Errorf("crypto.pbkdf2Sync has invalid signature")
}
digestArg := "null"
if len(instruction.Args) == 5 {
digestArg = fmt.Sprintf("%%%s", instruction.Args[4])
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_pbkdf2_sync(ptr %%%s, ptr %%%s, double %%%s, double %%%s, ptr %s, ptr %%%s)\n",
status, instruction.Args[0], instruction.Args[1], instruction.Args[2], instruction.Args[3], digestArg, slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.hkdfSync":
if len(instruction.Args) != 5 || instruction.Type != ir.TypeArrayBuffer {
return fmt.Errorf("crypto.hkdfSync has invalid signature")
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_hkdf_sync(ptr %%%s, ptr %%%s, ptr %%%s, ptr %%%s, double %%%s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], instruction.Args[2], instruction.Args[3], instruction.Args[4], slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
case "__crypto.scryptSync":
if len(instruction.Args) != 3 || instruction.Type != ir.TypeBuffer {
return fmt.Errorf("crypto.scryptSync has invalid signature")
}
slot := instruction.Result + ".slot"
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = alloca ptr\n", slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_crypto_scrypt_sync(ptr %%%s, ptr %%%s, double %%%s, ptr %%%s)\n", status, instruction.Args[0], instruction.Args[1], instruction.Args[2], slot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load ptr, ptr %%%s\n", instruction.Result, slot)
return nil
default:
return fmt.Errorf("unknown crypto intrinsic %q", instruction.Callee)
}
}

func (e *functionEmitter) emitDateIntrinsic(out *strings.Builder, instruction ir.Instruction) error {
switch instruction.Callee {
case "__date.now":
Expand Down
19 changes: 19 additions & 0 deletions internal/compiler/testdata/corpus/api/crypto.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cr_hash: 32 32
cr_hmac: 32
cr_hash_bytes: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 9c196e32dc0175f86f4b1cb89289d6619de6bee699e4c378e68309ed97a1a6ab
cr_hash_binary: 47ffa3ea45a70b8a41c2c0825df323c00a8b7a01c1ea06083cc41dddcc001123 963d16d355f11798a5434eaadf01feab4e09e8b31ddbdbc85a4c9a05f8dfb0b5
cr_x509: false 01 CN=Test true
cr_props: 1 true true
cr_sync: true true 32 32 16 true
cr_scrypt: 4cac4540992d51feeaefe4668bbfed7222f02b445aaffbbe60cfec110fb2735c
cr_hkdf: fe8f9615d2374c0d17f77d1aeaf408c2e75fe0466073d0def23c733e2f862dfd
cr_async: true
cr_keyobject: secret 32 true true 32
cr_rsa_keygen: public private rsa 2048
cr_cipher_cbc: Hello, ScriptGo Crypto!
cr_cipher_gcm: GCM authenticated payload 16 gcm
cr_sign_verify: true true
cr_asym_encrypt: Secret RSA Message
cr_dh: true 0 true true
cr_ecdh: true 32
cr_misc: 0 0 object
Loading
Loading